【问题标题】:Is dependency property same as a CLR property which emits a PropertyChanged event as callback?依赖属性是否与发出 PropertyChanged 事件作为回调的 CLR 属性相同?
【发布时间】:2016-04-10 06:41:50
【问题描述】:

这个问题与 WPF 数据绑定和 MVVM 模式有关。

我现在有点困惑,要区分 XAML.cs 文件中定义的 Dependency 属性以及绑定到组件的某些属性的视图模型中定义的 CLR 属性

例如,我在 MyPage.xaml 中有一个文本框。所以我创建了一个依赖属性来绑定 MyPage.xaml.cs 中的文本框文本属性,也许是一些字符串。下一次,我创建了一个 viewModel MyPageViewModel.cs ,它实现了 INotifyPropertyChanged 接口和 在那里创建了一个 CLR 属性(字符串),当它发生更改或属性设置为新值时,它会发出一个事件 PropertyChanged。那么这两者是一样的吗?有什么区别吗?

我有 3 个问题

  1. 依赖属性是否与 CLR 属性相同,CLR 属性在更改时会发出 PropertyChanged 事件?

  2. 依赖属性是写在视图本身(MyPage.xaml.cs)还是可以包含在视图中 模型(MyPageViewModel.cs)?

  3. 在 MVVM 模式中,我们更多地使用 CLR 属性,它在属性更改期间发出事件。所以可以替换依赖属性 通过这种 CLR 属性?

提前致谢。

【问题讨论】:

  • 您通常不会在视图模型中使用依赖属性。它们被用于视图元素,它们可以从数据绑定、样式、动画等中获取它们的值。
  • 依赖属性也会发出 NotifyChanged 事件,对吧?那么它和 ViewModel 属性一样吗?
  • 不完全是INotifyPropertyChanged接口的PropertyChanged事件,而是类似的通知机制。

标签: wpf xaml mvvm


【解决方案1】:

依赖属性位于 DependencyObject 上,所有 WPF UI 元素都从该 DependencyObject 派生(并且仅在其中工作),因为它是静态的,并将其值保存在分配给特定 DependencyObject 的一种集合中(在该集合上定义了依赖属性)。可以在实际 DependencyObject 之外的类中定义依赖属性,以扩展其功能,而无需修改原始用户控件类。

当您编写用户控件并希望 ViewModel 允许绑定值并在其更改时接收通知时,您需要创建一个依赖属性。

将它想象成一根 USB 电缆,其中有一个公插头和一个母插座。 CLR 属性就像插头,依赖属性就像插座。

依赖属性允许您存储与控件关联但不属于实例的内容。正如您在MSDN Examples 上看到的那样

public static readonly DependencyProperty IsSpinningProperty = 
    DependencyProperty.Register(
    "IsSpinning", typeof(Boolean),


...


    );
public bool IsSpinning
{
    get { return (bool)GetValue(IsSpinningProperty); }
    set { SetValue(IsSpinningProperty, value); }
}

依赖属性是静态的,GetValueSetValueDependencyObject(所有 WPF UI 元素都基于的基类)的方法。

依赖属性(和附加属性/附加行为)也可用于扩展UserControl 的功能,而无需从实际的用户控件类型继承,即当某个值发生更改时通知 ViewModel原始用户控制。

  1. 依赖属性是否与 CLR 属性相同,CLR 属性在更改时会发出 PropertyChanged 事件?

不,不一样。它们都是数据绑定引擎的两个方面。在视图上定义了一个 DP,以允许视图模型绑定一个 INPC 属性(上升的属性PropertyChanged 事件)

  1. Dependency 属性是写在视图本身中(MyPage.xaml.cs)还是可以包含在视图模型中(MyPageViewModel.cs)?

DP 是 View-Layer 的一部分,因为它们依赖于 DependencyObject,这是 WPF 框架的一部分,因此是视图关注点。虽然从技术上讲,没有什么可以阻止您在 ViewModel 中使用它们,但这会导致您的 ViewModel 与某种 View 技术紧密耦合,因此它不完全符合 MVVM 模式。

请注意,尽管对依赖属性进行单元测试可能非常困难,因为它们将值存储在定义它们的类上,而是存储在某种字典中,其中 GetValue/@ 987654333@ 方法扭曲。

最后但同样重要的是,因为DependencyObject 是所有 UI 的基类,它也是从它派生的大多数类线程仿射,这意味着您只能从您创建的线程访问它,这可能会导致您在单元测试(特别是如果测试像 MSTest 过去那样并行运行。不知道到今天仍然如此)和代码中都非常痛苦。

  1. 在 MVVM 模式中,我们更多地使用 CLR 属性,它在属性更改期间发出事件。那么依赖属性可以用这种CLR属性代替吗?

在 ViewModels 中你可以而且你应该使用INotifyPropertyChanged。如果您正在开发用户控件,则不应将 DP 替换为“CLR”属性,因为这会使该属性无法与 XAML 中的数据绑定一起使用。

如果您的 UI 元素应该公开一个可与数据绑定一起使用的属性,您必须使用依赖属性(或非常相似的附加属性,但您将附加属性放在子元素上。Grid.Row 和 @987654337 @ 是附加属性的示例)。

【讨论】:

  • “注册到用户控件(并且只在那里工作)”不正确。它可以在派生自 DependencyObject 的任何类型上注册和使用,这不一定是用户控件。尽管被认为是不好的做法,但人们甚至可以从 DependencyObject 派生他们的视图模型类,并在那里使用依赖属性。这样的设计既不是不可能的,也不是明确禁止的。
  • 点了。意思是说任何 UI 元素,所以我进行了编辑以使其更加清晰。对于第二部分,我只能说:在没有 OOP 的情况下仅使用静态方法或仅使用静态单例编写应用程序也不是不可能以过程方式编写代码,但认真的是哪个理智的开发人员会这样做?
  • 但我还是很困惑。这 3 个问题没有完全回答。
  • 非常感谢您的回答。
猜你喜欢
  • 2011-01-20
  • 2013-08-22
  • 2023-04-06
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 2014-06-14
  • 2011-01-29
相关资源
最近更新 更多