【问题标题】:When to use a WPF Dependency Property versus INotifyPropertyChanged何时使用 WPF 依赖属性与 INotifyPropertyChanged
【发布时间】:2011-04-02 20:19:08
【问题描述】:

对于在视图模型中触发INotifyPropertyChanged.PropertyChanged 的简单.NET 属性何时足够,人们是否有任何指导?那么你什么时候想升级到一个完整的依赖属性呢?还是 DP 主要用于查看?

【问题讨论】:

    标签: wpf binding dependency-properties inotifypropertychanged


    【解决方案1】:

    据我所知,DependencyProperty只有在你需要的时候才需要

    1. PropertyValue 继承
    2. 您需要允许在样式设置器中设置属性
    3. 为属性使用动画

    等等。

    这些功能不适用于普通属性。

    【讨论】:

      【解决方案2】:

      有几种方法:

      1.依赖属性

      当您使用依赖属性时,它在具有视觉外观的元素类中最有意义 (UIElements)。

      优点:

      • 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 如果要允许在属性上设置绑定,则需要。通常这是针对您创建的自定义UIElements。您希望人们能够将数据绑定到您的UIElements。

      <local:MyUIElement MyProperty={Binding Path=SomethingToBindTo} />
      

      要做到这一点,需要 MyProperty 是一个依赖属性

      【讨论】:

      • 这其实是正确的答案。如果您希望属性成为绑定的目标,则只需要 DependencyProperty。除此之外,如果需要,您可以使用标准属性加上 INotifyPropertyChanged。
      • 我很确定我用INotifyPropertyChanged 做了很多次,您的回答中是否有任何“隐藏方面”不清楚?
      【解决方案4】:

      我看到INotifyPropertyChanged 的主要问题是,如果您的视图模型很复杂,包含许多嵌套类型,您似乎必须将PropertyChanged 事件通过层次结构向上冒泡。

      【讨论】:

        【解决方案5】:

        正如其他答案已经充分说明了何时创建依赖属性。即

        1. PropertyValue 继承
        2. 您需要对属性使用绑定
        3. 为属性使用动画

        对此的另一个观点/问题是“在 WPF 应用程序中,在控件中创建依赖属性是有意义的,因为它们可能会在用户交互过程中发生变化,例如高度、宽度、文本、内容、背景等 但是像 Behaviors Classes(非 UI 类)这样的其他类呢。这些类中的属性是否需要是依赖属性?”

        我不会在这里说非常绝对或强调某些规则,但您应该将属性创建为 DP。从设计的角度来看,如果一个属性是 DP,它总是以 WPF 的默认形式使用/bind.i.e.

        1. 与普通 CLR 属性相比,DP 在反映变化方面更快/更自然。
        2. DP 具有验证机制来验证分配的值和恢复值的默认结构。
        3. DP 具有强制值回调来控制属性的限制。
        4. 与 CLR 属性不同,DP 具有与其关联的元数据。

        在实践方面,我看到人们在嵌套绑定中犯了很多错误,然后引发更改,这些错误不会发生在 DP 中,因为它的设计和引发更改本身的兼容性。因此,通过一些额外的语法,您可以为您的应用程序带来灵活性/性能/易用性。所以去任何负担得起的地方。

        仍然不能确定 ViewModel 类/其他辅助类。如果将来找到令人信服的理由,将更新答案。

        Just a post worth reading on this topic

        【讨论】:

          猜你喜欢
          • 2013-08-12
          • 2014-05-23
          • 2011-09-25
          • 2011-07-22
          • 2011-09-02
          • 1970-01-01
          • 2023-03-19
          相关资源
          最近更新 更多