在WPF中对ToggleButton的IsChecked属性进行OneWay绑定

时间:2010-09-22 16:25:30

标签: wpf data-binding togglebutton

我有一个ToggleButton,其IsChecked属性使用OneWay绑定绑定到属性。

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

SomeCommand切换布尔SomeProperty值,并为PropertyChanged引发SomeProperty事件。

如果我在视图模型中更改SomeProperty,则ToggleButton会正确按下。但是,如果我单击ToggleButton,绑定似乎会丢失,并且不再根据SomeProperty的值检查按钮。关于如何解决这个问题的任何想法?

5 个答案:

答案 0 :(得分:11)

有一种简单而优雅的方法来解决原始海报的问题 - 将ToggleButton的IsChecked属性替换为可附加属性,该属性将在其更改处理程序中设置按钮的IsChecked:

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将如下所示:

<ToggleButton Command="{Binding Path=SomeCommand}"
              TBFix:TBExtender.IsChecked="{Binding Path=SomeProperty,
                                                   Mode=OneWay}" />
编辑:OP解决方案不起作用,因为当按下按钮时,IsChecked属性在代码中设置(这是MS实现ToggleButton控件的方式) - 设置属性会从中删除绑定,因此它停止工作

通过使用附加属性,我们可以克服这个问题,因为它从未在代码中赋值,因此绑定保持不变。

答案 1 :(得分:5)

这是设计时使用单向数据绑定。将附加属性PresentationTraceSources.TraceLevel = High添加到绑定中,您将看到它何时断开连接。此链接也描述了该问题(未提供任何解决方案):Debugging Data Binding in WPF

我通常解决的方法是使用命令进行用户交互,然后使用代码更改控件外观,因为某些更改的属性。

答案 2 :(得分:1)

我有类似的问题。

“绑定似乎迷失”(除非是早期的框架问题)。绑定继续工作,可以通过更改该命令之外的属性轻松证明(例如,在另一个按钮单击事件/命令的处理程序中)。

问题在于IsChecked可以通过两种方式进行更改:1)绑定(当SomeProperty的值被更改时,按钮将被更新2)用户(如果用户按下按钮,他将更改{{ 1}},但绑定为IsChecked,因此OneWay不会更新。

因此,SomeProperty可能会发生 desync ,但会按SomeProperty == false,反之亦然。

优化性能绑定机制是检查新值是否与当前值不同。因此,如果发生了异步,并且您尝试使用已有的值更新IsChecked == true,则不会发生任何事情。

解决方法很简单:分两步更新属性

SomeProperty

其中SomeProperty = !set; SomeProperty = set; 是您需要的值(例如,与当前set相反)。

答案 3 :(得分:0)

我认为问题归结为命令与IsChecked绑定之间的冲突。我的解决方案是更改我的viewmodel以公开bool?并将其绑定到IsChecked属性。我没有将命令绑定到ToggleButton。在我的代码中,我要切换属性,我使用SomeCommand

答案 4 :(得分:0)

据我所知,Sinatr对于&#39; desync&#39;是正确的。这种情况至少在较新的框架中发生。

解决这个问题的另一个简单方法是删除mode = oneway并实现一个空的setter。例如:

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

使用此绑定设置,您可以从命令绑定功能更改支持变量的值,或者从是否需要更改。只记得调用RaisePropertyChanged。