2010-09-22 12 views
8

Mam wartość ToggleButton z jej właściwością IsChecked powiązaną z właściwością za pomocą wiązania OneWay.Wiązanie OneWay dla właściwości IsChecked ToggleButton w WPF

<ToggleButton 
    Command="{Binding Path=SomeCommand}" 
    IsChecked="{Binding Path=SomeProperty, Mode=OneWay}" /> 

SomeCommand przełącza wartość logiczną SomeProperty, a zdarzenie PropertyChanged jest podniesiony SomeProperty.

Jeśli zmienię SomeProperty w moim modelu wyświetlania, ToggleButton naciska prawidłowo. Jeśli jednak kliknę przycisk ToggleButton, utrata połączenia zostanie utracona, a przycisk nie będzie już sprawdzany zgodnie z wartością SomeProperty. Wszelkie pomysły dotyczące rozwiązania tego problemu?

+0

Co robi Twoja komórka SomeCommand? Mam wiele ToggleButtonów, które robią to samo, z tym samym rodzajem wiązania, a wszystkie SomeCommand nie negują bieżącej wartości SomeProperty. –

+0

SomeProperty był w rzeczywistości innym typem i używałem konwertera, aby zmienić go na boolowski. Zostawiłem to, aby pytanie stało się prostsze. –

Odpowiedz

4

Jest to zgodne z projektem, gdy używane jest jednokierunkowe powiązanie danych. Dodaj dołączoną właściwość PresentationTraceSources.TraceLevel = Wysoka do wiązania, a zobaczysz, kiedy zostanie odłączony. To łącze również opisuje problem (bez oferowania żadnego rozwiązania): Debugging Data Binding in WPF

Sposób, w jaki normalnie go rozwiązuję, polega na użyciu polecenia dla interakcji użytkownika i kodu źródłowego, aby zmienić wygląd kontrolki z powodu pewnych zmienionych właściwości.

+0

Dlaczego ta odpowiedź została zaakceptowana? Nie rozwiązuje problemu (który istnieje i może być łatwo odtworzony). – Sinatr

0

Myślę, że problemem jest spór między poleceniem a powiązaniem IsChecked. Moim rozwiązaniem było zmienić mój model widoku, aby odsłonić bool? i powiązać go z właściwością IsChecked. Nie powiązałem polecenia z ToggleButton. Gdzie indziej w moim kodzie, gdzie chcę przełączyć nieruchomość używam SomeCommand.

10

Istnieje prosty i elegancki sposób na rozwiązanie pierwotnego autora problemu - zastępując IsChecked własność ToggleButton z własności przyczepnego, który będzie ustawiony IsChecked przycisku w jego obsługi Zmiana:

namespace TBFix 
{ 
    public class TBExtender 
    { 
    public static readonly DependencyProperty IsCheckedProperty = 
     DependencyProperty.RegisterAttached("IsChecked", 
              typeof(bool), 
              typeof(TBExtender), 
              new PropertyMetadata(OnChanged)); 

    public static bool GetIsChecked(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsCheckedProperty); 
    } 
    public static void SetIsChecked(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsCheckedProperty, value); 
    } 

    private static void OnChanged(DependencyObject o, 
            DependencyPropertyChangedEventArgs args) 
    { 
     ToggleButton tb = o as ToggleButton; 
     if (null != tb) 
     tb.IsChecked = (bool)args.NewValue; 
    } 
    } 
} 

XAML wtedy wyglądać tak:

<ToggleButton Command="{Binding Path=SomeCommand}" 
       TBFix:TBExtender.IsChecked="{Binding Path=SomeProperty, 
                Mode=OneWay}" /> 

EDIT: rozwiązanie OP nie działa, ponieważ gdy przycisk jest wciśnięty IsChecked właściwość jest ustawiona w kodzie (w ten sposób MS realizowane sterowanie ToggleButton) - ustawienie właściwości usuwa wiązanie fr om, a więc przestaje działać.

Korzystając z załączonej właściwości, możemy przezwyciężyć ten problem, ponieważ nigdy nie przypisuje się jej wartości w kodzie, przez co wiązania pozostają nienaruszone.

+0

Cześć Alex, Dzięki za zapewnienie eleganckiego rozwiązania, to działa dla mnie. ale nie rozumiem, jak to działa. Czy możesz wyjaśnić trochę więcej? –

+0

Dodałem kilka słów na temat idei mojego rozwiązania. Możesz przeczytać więcej o załączonych właściwościach na MSDN (http://msdn.microsoft.com/en-us/library/vstudio/ms749011(v=vs.100).aspx) –

+0

To jest rzeczywiście eleganckie! – akshay2000

1

Mam podobny problem.

nie jest „wiązanie wydaje się zgubić” (chyba że jest wcześniejsze Ramki problemy). Wiązanie działa nadal i można je łatwo dowieść, zmieniając właściwość spoza zakresu , która to komenda to (np. W programie obsługi zdarzenia/polecenia innego kliknięcia przycisku).

Problemem jest to, co IsChecked można zmienić na dwa sposoby: 1) wiązanie (gdy wartość SomeProperty zostanie zmieniony przycisk zostaną zaktualizowane 2) użytkownika (jeśli nacisnąć przycisk użytkownik będzie zmienić IsChecked, ale wiązanie jest OneWay tak SomeProperty będzie nie być aktualizowanym).

Więc może trzeba utratę synchronizacji występuje, gdy SomeProperty == false ale przycisk IsChecked == true lub vice versa.

Aby zoptymalizować mechanizm łączenia wydajności, należy sprawdzić, czy nowa wartość różni się od aktualnej. Więc jeśli wystąpi desynchronizacja i spróbujesz zaktualizować SomeProperty z wartością, którą już posiada, wtedy nic się nie stanie.

Obejście jest prosty: własność zmiana w 2 kroki

SomeProperty = !set; 
SomeProperty = set; 

gdzie set jest wartość co potrzeba (na przykład przeciwny do obecnego SomeProperty).

0

Według mojej wiedzy Sinatr ma rację co do "desynchronizacji", która ma miejsce, przynajmniej w nowszych ramach.

Innym prostym sposobem obejścia problemu jest usunięcie trybu = jednokierunkowego i zaimplementowanie pustego ustawiacza. Ex:

bool _MyIsEnabled; 
    public bool MyIsEnabled 
    { 
     get { return _MyIsEnabled; } 
     set { } 
    } 

Dzięki tej konfiguracji wiązania można zmienić wartość zmiennej podkładowej z funkcji wiążących poleceń, lub od tego, czy trzeba. Pamiętaj tylko, aby zadzwonić do RaisePropertyChanged.

Powiązane problemy