10 Stimmen

OneWay-Bindung für die IsChecked-Eigenschaft von ToggleButton in WPF

J'ai un ToggleButton mit seinem IsChecked Eigenschaft, die über eine OneWay-Bindung an eine Eigenschaft gebunden ist.

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

Le site SomeCommand schaltet den booleschen Wert SomeProperty Wert, und ein PropertyChanged Ereignis wird ausgelöst für SomeProperty .

Wenn ich die SomeProperty in meinem Viewmodel die ToggleButton richtig eindrückt. Wenn ich jedoch auf die ToggleButton scheint die Bindung verloren zu gehen und die Schaltfläche wird nicht mehr entsprechend dem Wert von SomeProperty . Haben Sie eine Idee, wie man dieses Problem beheben kann?

13voto

Alex_P Punkte 1826

Es gibt einen einfachen und eleganten Weg, um das Problem des ursprünglichen Posters zu lösen - das Ersetzen der IsChecked-Eigenschaft des ToggleButtons durch eine attachable-Eigenschaft, die IsChecked des Buttons in seinem Change-Handler setzt:

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 sieht dann wie folgt aus:

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

EDIT: Die OP-Lösung funktioniert nicht, weil, wenn die Schaltfläche gedrückt wird, die IsChecked-Eigenschaft im Code festgelegt ist (dies ist die Art und Weise MS implementiert ToggleButton-Steuerelement) - Einstellung der Eigenschaft entfernt die Bindung von ihm und so es nicht mehr funktioniert.

Durch die Verwendung der angehängten Eigenschaft können wir dieses Problem umgehen, da ihr im Code nie ein Wert zugewiesen wird und die Bindungen somit intakt bleiben.

7voto

Wallstreet Programmer Punkte 9389

Dies ist bei der Verwendung der einseitigen Datenbindung so vorgesehen. Fügen Sie die angehängte Eigenschaft PresentationTraceSources.TraceLevel=High zu Ihrer Bindung hinzu und Sie werden sehen, wann die Verbindung unterbrochen wird. Dieser Link beschreibt das Problem ebenfalls (ohne eine Lösung anzubieten): Debuggen von Datenbindungen in WPF

Normalerweise verwende ich einen Befehl für die Benutzerinteraktion und Code dahinter, um das Aussehen des Steuerelements aufgrund geänderter Eigenschaften zu ändern.

3voto

raistlin Punkte 31

Meines Wissens hat Sinatr recht, was die "Desynchronisation" betrifft, die zumindest in neueren Frameworks auftritt.

Eine andere einfache Möglichkeit, das Problem zu umgehen, besteht darin, die Option mode=oneway zu entfernen und einen leeren Setter zu implementieren. Bsp:

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

Mit diesem Bindungssetup können Sie den Wert der Backing-Variable von Ihrer Befehlsbindungsfunktion aus ändern, oder ob Sie das müssen. Denken Sie einfach daran, RaisePropertyChanged aufzurufen.

0voto

sourcenouveau Punkte 27697

Ich denke, dass das Problem auf einen Konflikt zwischen dem Befehl und dem IsChecked Bindung. Meine Lösung bestand darin, mein Viewmodel so zu ändern, dass es eine bool? und binden diese an die IsChecked Eigentum. Ich habe keinen Befehl an die Eigenschaft ToggleButton . An anderer Stelle in meinem Code, wo ich die Eigenschaft umschalten möchte, verwende ich SomeCommand .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X