何时使用 WPF 依赖属性与 INotifyPropertyChanged

发布于 2024-09-15 19:59:54 字数 124 浏览 5 评论 0原文

对于何时在视图模型中触发 INotifyPropertyChanged.PropertyChanged 的​​简单 .NET 属性就足够了,人们是否有任何指导?那么您什么时候想升级到完整的依赖属性呢?或者说 DP 主要是为了获取观点?

Do folks have any guidance on when a simple .NET property that fires INotifyPropertyChanged.PropertyChanged is sufficient in a view model? Then when do you want to move up to a full blown dependency property? Or are the DPs intended primarily for views?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

踏月而来 2024-09-22 19:59:55

有几种方法:

1。依赖属性

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

优点:

  • WPF 为您做逻辑工作
  • 一些机制(例如动画)仅使用依赖属性
  • “适合”ViewModel 样式

缺点:

  • 您需要派生形式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.PropertyNameChanged

为具有指定名称 (fe NameChanged) 的每个属性引发一个事件。事件必须具有此名称,并且由您来处理/引发它们。 类似的方法

与 2. 4. 。获取绑定

使用FrameworkElement.GetBindingExpression(),您可以获得BindingExpression 对象
并调用 BindingExpression.UpdateTarget() 进行刷新。

第一个和第二个最有可能取决于您的目标是什么。

总而言之,这是视觉与数据。

There are a few approaches:

1. The dependency property

While you using the dependency property it makes the most sense in elements-classes that have a visual appearance (UIElements).

Pros:

  • WPF do the logic stuff for you
  • Some mechanism like animation use only dependency property
  • 'Fits' ViewModel style

Cons:

  • You need to derive form DependencyObject
  • A bit awkward for simple stuff

Sample:

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. The System.ComponentModel.INotifyPropertyChanged

Usually, when creating a data object, you’ll use this approach. It is simple and neat solution for Data-like stuff.

Pros and Cons - complementary to 1. You need to to implement only one event (PropertyChanged).

Sample:

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.PropertyNameChanged

Rising an event for each property with specified name(f.e. NameChanged). Event must have this name and it is up to you to handle/rise them. Similar approach as 2.

4. Get the binding

Using the FrameworkElement.GetBindingExpression() you can get the BindingExpression object
and call BindingExpression.UpdateTarget() to refresh.

First and second are the most likely depending what is your goal.

All in all, it is Visual vs Data.

陌若浮生 2024-09-22 19:59:55

据我所知,仅当您需要

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

等。

这些功能对于普通属性将不可用。

As far as I know, DependencyProperty is only required when you need

  1. PropertyValue inheritence
  2. you need to allow the property to be set in Style setters
  3. Use animation for the property

etc.

These features will not be available with normal properties.

找回味觉 2024-09-22 19:59:55

如果您希望允许在属性上设置绑定,则需要 DependencyProperty。通常这适用于您创建的自定义 UIElement。您希望允许人们将数据绑定到您的 UIElement

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

为此,需要 MyProperty 是依赖属性

DependencyProperty is required if you want to allow a binding to be set on the property. Usually this is for custom UIElements you create. You want to allow people to be able to bind data to your UIElements.

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

To do this requires that MyProperty is a dependancy property

花伊自在美 2024-09-22 19:59:55

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

The main problem I see with INotifyPropertyChanged is if you viewmodel is complex containing many nested types it appears that you have to bubble the PropertyChanged event up through the hierarchy.

熊抱啵儿 2024-09-22 19:59:55

正如其他答案已经足够说明何时创建依赖属性一样。 IE

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

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

我不会说太多。绝对或强调此处的某些规则集,但您应该将属性创建为 DP。从设计角度来看,如果属性是 DP,它始终以 WPF 的默认形式使用/bind.ie

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

在实践方面,我看到人们在嵌套绑定中犯了很多错误,然后引发了更改,这种错误不会发生在 DP 中,因为它的设计和引发更改本身的兼容性。因此,通过一些额外的语法,您可以为应用程序提供灵活性/性能/易用性。因此,只要价格实惠,就去买吧。

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

关于这个主题的一篇文章值得一读

As the other answers have already said enough about when to create dependency property. i.e.

  1. PropertyValue inheritence
  2. you need to use binding on a property
  3. Use animation for the property

The one more perspective/question on this is "In a WPF application is makes sense to create dependency properties in a control cause they are likely to change during user interaction like Height,width, text,content, background etc but what about other classes like Behaviors Classes(Non UI classes). Do properties in those classes need to be a dependency property?"

I won't say for very absolute or emphasis on some set of rules here but you should create your properties as DP. As from design perspective if a property is DP it's always in default form of WPF to use/bind.i.e.

  1. As a DP is much more fast/natural in reflecting changes compare to a normal CLR property.
  2. A DP has validation mechanism to validate the value assigned and a default structure to revert the value.
  3. A DP has Coerce value callback to control the limits of property.
  4. A DP has meta data associated with it unlike CLR property.

In terms of practices I've seen people doing many mistakes in nested bindings and then raising changes these kind of faults doesn't happen with a DP cause of it's design and compatibility of raising change itself. So with a little extra syntax you put a flexibility/performance/ easeness to your application. So go for it wherever affordable.

Still can't say sure for ViewModel classes/other helper classes. will update the answer if found convincing reasons in future.

Just a post worth reading on this topic

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文