何时使用 WPF 依赖属性与 INotifyPropertyChanged
Posted
技术标签:
【中文标题】何时使用 WPF 依赖属性与 INotifyPropertyChanged【英文标题】:When to use a WPF Dependency Property versus INotifyPropertyChanged 【发布时间】:2011-04-02 20:19:08 【问题描述】:对于在视图模型中触发INotifyPropertyChanged.PropertyChanged
的简单.NET 属性何时足够,人们是否有任何指导?那么你什么时候想升级到一个完整的依赖属性呢?还是 DP 主要用于查看?
【问题讨论】:
【参考方案1】:据我所知,DependencyProperty
只有在你需要的时候才需要
-
PropertyValue 继承
您需要允许在样式设置器中设置属性
为属性使用动画
等等。
这些功能不适用于普通属性。
【讨论】:
【参考方案2】:有几种方法:
1.依赖属性
当您使用依赖属性时,它在具有视觉外观的元素类中最有意义 (UIElement
s)。
优点:
WPF 为你做逻辑工作 像动画这样的一些机制只使用依赖属性 “适合”视图模型样式缺点:
你需要派生出DependencyObject
的形式
简单的东西有点尴尬
示例:
public static class StoryBoardHelper
public static DependencyObject GetTarget(Timeline timeline)
if (timeline == null)
throw new ArgumentNullException("timeline");
return timeline.GetValue(TargetProperty) as DependencyObject;
public static void SetTarget(Timeline timeline, DependencyObject value)
if (timeline == null)
throw new ArgumentNullException("timeline");
timeline.SetValue(TargetProperty, value);
public static readonly DependencyProperty TargetProperty =
DependencyProperty.RegisterAttached(
"Target",
typeof(DependencyObject),
typeof(Timeline),
new PropertyMetadata(null, OnTargetPropertyChanged));
private static void OnTargetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
Storyboard.SetTarget(d as Timeline, e.NewValue as DependencyObject);
2。 System.ComponentModel.INotifyPropertyChanged
通常,在创建数据对象时,您会使用这种方法。对于类似数据的东西来说,这是一个简单而整洁的解决方案。
优点和缺点 - 对 1 的补充。您只需要实现一个事件 (PropertyChanged)。
示例:
public class Student : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
if (PropertyChanged != null)
PropertyChanged(this, e);
private string name;
public string Name;
get return name;
set
name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
3.PropertyName已更改
为具有指定名称的每个属性(例如 NameChanged)触发一个事件。事件必须具有此名称,由您来处理/提升它们。方法与 2 类似。
4.获取绑定
使用FrameworkElement.GetBindingExpression()
可以获得BindingExpression
对象
并调用BindingExpression.UpdateTarget()
刷新。
第一和第二最有可能取决于您的目标。
总而言之,就是视觉 vs 数据。
【讨论】:
这是一个很好的答案,值得更多的支持!如果可以的话,我会投票两次。 :-)【参考方案3】:DependencyProperty
如果要允许在属性上设置绑定,则需要。通常这是针对您创建的自定义UIElement
s。您希望人们能够将数据绑定到您的UIElement
s。
<local:MyUIElement MyProperty=Binding Path=SomethingToBindTo />
要做到这一点,需要 MyProperty 是一个依赖属性
【讨论】:
这其实是正确的答案。如果您希望属性成为绑定的目标,则只需要 DependencyProperty。除此之外,如果需要,您可以使用标准属性加上 INotifyPropertyChanged。 我很确定我用INotifyPropertyChanged
做了很多次,您的回答中是否有任何“隐藏方面”不清楚?【参考方案4】:
我看到INotifyPropertyChanged
的主要问题是,如果您的视图模型很复杂,包含许多嵌套类型,您似乎必须将PropertyChanged
事件通过层次结构向上冒泡。
【讨论】:
【参考方案5】:正如其他答案已经充分说明了何时创建依赖属性。即
PropertyValue 继承 您需要对属性使用绑定 为属性使用动画
对此的另一个观点/问题是“在 WPF 应用程序中,在控件中创建依赖属性是有意义的,因为它们可能会在用户交互过程中发生变化,例如高度、宽度、文本、内容、背景等 但是像 Behaviors Classes(非 UI 类)这样的其他类呢。这些类中的属性是否需要是依赖属性?”
我不会在这里说非常绝对或强调某些规则,但您应该将属性创建为 DP。从设计的角度来看,如果一个属性是 DP,它总是以 WPF 的默认形式使用/bind.i.e.
与普通 CLR 属性相比,DP 在反映变化方面更快/更自然。 DP 具有验证机制来验证分配的值和恢复值的默认结构。 DP 具有强制值回调来控制属性的限制。 与 CLR 属性不同,DP 具有与其关联的元数据。
在实践方面,我看到人们在嵌套绑定中犯了很多错误,然后引发更改,这些错误不会发生在 DP 中,因为它的设计和引发更改本身的兼容性。因此,通过一些额外的语法,您可以为您的应用程序带来灵活性/性能/易用性。所以去任何负担得起的地方。
仍然不能确定 ViewModel 类/其他辅助类。如果将来找到令人信服的理由,将更新答案。
Just a post worth reading on this topic
【讨论】:
以上是关于何时使用 WPF 依赖属性与 INotifyPropertyChanged的主要内容,如果未能解决你的问题,请参考以下文章