【问题标题】:OneWay binding for ToggleButton's IsChecked property in WPFWPF 中 ToggleButton 的 IsChecked 属性的 OneWay 绑定
【发布时间】:2011-04-15 20:18:26
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您的 SomeCommand 是做什么的?我有许多 ToggleButtons 做同样的事情,具有相同类型的绑定,而 SomeCommand 所做的就是否定 SomeProperty 的当前值。
  • SomeProperty 实际上是一种不同的类型,我使用转换器将其更改为布尔值。为了让问题更简单,我把它省略了。

标签: wpf data-binding togglebutton


【解决方案1】:

有一种简单而优雅的方法可以解决原始海报的问题 - 将 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 控件的方式) - 设置属性会从中删除绑定,因此它停止工作.

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

【讨论】:

  • 嗨,Alex,感谢您提供优雅的解决方案,它对我有用。但我不明白它是如何工作的。你能再解释一下吗?
  • 我对我的解决方案背后的想法添加了几句话。您可以在 MSDN (msdn.microsoft.com/en-us/library/vstudio/…) 上阅读有关附加属性的更多信息
  • 这确实很优雅!
【解决方案2】:

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

我通常解决它的方法是使用用户交互的命令和代码来更改控件的外观,因为一些更改的属性。

【讨论】:

  • 为什么这个答案被接受了?它不能解决问题(存在并且可以轻松复制)。
【解决方案3】:

据我所知,Sinatr 关于发生的“不同步”是正确的,至少在较新的框架中是这样。

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

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

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

【讨论】:

  • 喜欢这种简单的解决方法 - 有点 hacky,但比创建自定义控件更简单
【解决方案4】:

我也有类似的问题。

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

问题是IsChecked 可以通过两种方式更改:1)绑定(当SomeProperty 的值更改时按钮将被更新2)用户(如果用户按下按钮他将更改IsChecked,但绑定是OneWay 所以SomeProperty 不会更新)。

所以当SomeProperty == false 但按钮IsChecked == true 或反之亦然时,您可能会出现desync

优化性能绑定机制是检查新值是否与当前值不同。因此,如果发生异步并且您尝试使用它已经拥有的值更新SomeProperty,那么什么都不会发生。

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

SomeProperty = !set;
SomeProperty = set;

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-26
      相关资源
      最近更新 更多