在我的场景中,我有很多按钮或其他控件,我想依赖于代码隐藏文件中的公共属性。我们称之为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属性
按钮 依赖答案 0 :(得分:4)
您的按钮(即数据绑定)需要通知您的公共财产已更改。这可以通过两种方式完成:
INotifyPropertyChanged
并在更改PropertyChanged
或IsEverythingLoaded
事件
对于第一种选择,托马斯写了一个例子;对于第二个选项,您的代码将如下所示:
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绑定可能被认为是良好的设计,不错:
将DependencyProperty绑定到另一个DependencyProperty 更高效,而不是将其绑定到实现INotifyPropertyChanged的CLR属性。此用例已在WPF中进行了大量优化,并且是您期望的方式。
DependencyProperties 更不容易出错,以保持数据同步。很容易忘记调用PropertyChanged事件或者没有正确分析您可能需要调用它的所有情况。 DependencyProperties可以减轻您的负担。由于我主要使用INotifyPropertyChanged切换到主要使用DependencyProperties,我的数据错误同步错误大约减少了100倍几乎为零,而且几乎总是留在INotifyPropertyChanged代码中的那些错误。
在编写代码演示文稿时,您经常意外地想到了将您一直视为纯粹的“数据”属性的动画。如果它不是DependencyProperty,则无法完成。我可以向您展示几个使用DependencyProperties真正节省了一天的例子。
如果操作正确,创建DependencyProperty作为数据源比支持INotifyPropertyChanged的相应CLR属性更少代码(和更简单)。
如果您使用DependencyProperty作为源,则可以使用业务规则添加强制和验证,这不能通过CLR属性来完成。
许多DependencyProperties的存储比许多CLR属性更高效,使它们非常适合具有许多'null',0,'false'或'Empty'属性值的数据对象
DependencyProperties提供了一个出色的线程安全机制,因为如果您尝试不当地使用它们而不是默默地做错事,它们会立即提醒您。
如果您绑定到DependencyProperties,绑定可以在必要时自动安全地交叉线程。如果绑定到CLR属性,则根本没有保护,因此唯一安全的方法是在应用程序具有多个线程时将lock()代码锁定到对象。由于缓存和加载/商店订购规则可能产生的细微线程问题,不这样做会充满危险。
DependencyProperties可以使用OverrideMetadata有效支持按对象类型更改默认值。经典CLR属性只能通过在每次构造对象时运行额外的代码来实现。
我可以继续并列出使用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
}