将IsEnabled和其他属性绑定到公共属性,它是否像依赖属性一样工作?

时间:2009-11-18 13:46:41

标签: c# .net wpf binding

在我的场景中,我有很多按钮或其他控件,我想依赖于代码隐藏文件中的公共属性。我们称之为IsEverythingLoaded,它是一个布尔值。

现在我想要一个像这样的按钮

<Button Click="DoTheMagic" 
     IsEnabled="{Binding Path=IsEverythingLoaded}">Click Me</Button>

为了让这个运行起来我发现我需要将它指向相对源,所以通过将其添加到我的<Window> decleration,我得到启动和可视化工作。

DataContext="{Binding RelativeSource={RelativeSource Self}}"

但是,让我说我用另一个按钮引发一个事件,然后将IsEverythingLoaded设置为true,我想每个按钮上的IsEnabled也是如此。因此可以再次点击,但我错了,这不是DependencyProperties应该如何工作的吗?

澄清..

NOT 希望将IsEverythingLoaded写为DependencyProperty。我希望一个CLR属性

按钮 依赖

3 个答案:

答案 0 :(得分:4)

您的按钮(即数据绑定)需要通知您的公共财产已更改。这可以通过两种方式完成:

  • 让您的班级实施INotifyPropertyChanged并在更改PropertyChanged
  • 后举起IsEverythingLoaded事件
  • 使您的公共属性成为DependencyProperty,在这种情况下,通知由框架自动完成。 DependencyProperty MSDN page包含进一步的解释和如何执行此操作的示例。

对于第一种选择,托马斯写了一个例子;对于第二个选项,您的代码将如下所示:

public static readonly DependencyProperty IsEverythingLoadedProperty =
    DependencyProperty.Register("IsEverythingLoaded", typeof(Boolean),
                                 typeof(YourCodeBehindClass), new PropertyMetadata(false));

public Boolean IsEverythingLoaded {
    get { return (Boolean)this.GetValue(IsEverythingLoadedProperty); }
    set { this.SetValue(IsEverythingLoadedProperty, value); } 
}

答案 1 :(得分:4)

我非常不同意你对绑定DP的一揽子声明 - > DP是“糟糕的设计”。

以下是DP - >的一些原因。 DP绑定可能被认为是良好的设计,不错:

  1. 将DependencyProperty绑定到另一个DependencyProperty 更高效,而不是将其绑定到实现INotifyPropertyChanged的CLR属性。此用例已在WPF中进行了大量优化,并且是您期望的方式。

  2. DependencyProperties 更不容易出错,以保持数据同步。很容易忘记调用PropertyChanged事件或者没有正确分析您可能需要调用它的所有情况。 DependencyProperties可以减轻您的负担。由于我主要使用INotifyPropertyChanged切换到主要使用DependencyProperties,我的数据错误同步错误大约减少了100倍几乎为零,而且几乎总是留在INotifyPropertyChanged代码中的那些错误。

  3. 在编写代码演示文稿时,您经常意外地想到了将您一直视为纯粹的“数据”属性的动画。如果它不是DependencyProperty,则无法完成。我可以向您展示几个使用DependencyProperties真正节省了一天的例子。

  4. 如果操作正确,创建DependencyProperty作为数据源比支持INotifyPropertyChanged的相应CLR属性更少代码(和更简单)。

  5. 如果您使用DependencyProperty作为源,则可以使用业务规则添加强制和验证,这不能通过CLR属性来完成。

  6. 许多DependencyProperties的存储比许多CLR属性更高效,使它们非常适合具有许多'null',0,'false'或'Empty'属性值的数据对象

  7. DependencyProperties提供了一个出色的线程安全机制,因为如果您尝试不当地使用它们而不是默默地做错事,它们会立即提醒您。

  8. 如果您绑定到DependencyProperties,绑定可以在必要时自动安全地交叉线程。如果绑定到CLR属性,则根本没有保护,因此唯一安全的方法是在应用程序具有多个线程时将lock()代码锁定到对象。由于缓存和加载/商店订购规则可能产生的细微线程问题,不这样做会充满危险。

  9. DependencyProperties可以使用OverrideMetadata有效支持按对象类型更改默认值。经典CLR属性只能通过在每次构造对象时运行额外的代码来实现。

  10. 我可以继续并列出使用DependencyProperties作为绑定源的其他一些好理由,但我认为你明白了。

    WPF是基于您将绑定到DependencyProperties的假设而构建的,而INotifyPropertyChanged仅在稍后添加(并且效率低下)。这证明了一组非常优秀的软件架构师清楚地认为绑定DP - > DP是一个很好的设计。

    我意识到在某些情况下使用INotifyPropertyChanged而不是DP有一些优点。然而,DP - > DP绑定肯定不是“糟糕的设计”,在很多情况下它是最好的设计。

答案 2 :(得分:2)

您的类需要实现INotifyPropertyChanged,以便它可以通知绑定属性值已更改。

public class MyClass : INotifyPropertyChanged
{
    public bool IsEverythingLoaded
    {
        get { return _isEverythingLoaded; }
        set
        {
            _isEverythingLoaded = value;
            OnPropertyChanged("IsEverythingLoaded");
        }
    }

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
       PropertyChangedEventHandler handler = PropertyChanged;
       if (handler != null)
           handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}