通过静态属性而不是静态字段公开DependencyProperty的主要缺点是什么?(F#)

sta*_*ica 10 wpf f# dependency-properties

我发现F#2.0显然不再支持公共静态字段,这使得标准的实现方式变得不可能DependencyProperty:

public static readonly FooProperty = DependencyProperty.Register(...);   // in C#
Run Code Online (Sandbox Code Playgroud)

我不太喜欢F#的一个建议解决方法,它涉及将DependencyPropertya 声明为a static mutable val然后用static do... 初始化它(或者不管它究竟是什么).

我已经尝试将一个DependencyProperty公共静态属性公开,而不是公共静态字段,这似乎在WPF应用程序中工作得很好(我已经在属性上尝试了数据绑定和样式设置器,两者都成功):

type XY() =
   inherit Control()

   static let fooProperty =
      DependencyProperty.Register("Foo", typeof<string>, typeof<XY>) 

   static member public FooProperty with get () = fooProperty  // see update below:
   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  // not required!

   member public this.Foo with get (): string = this.GetValue(fooProperty) :?> string
                          and set (x: string) = this.SetValue(fooProperty, x)
Run Code Online (Sandbox Code Playgroud)

将依赖项属性作为属性而不是作为字段发布是否存在明显的缺点?因为这个代码对我来说比建议的解决方案看起来更干净.


更新#1:我刚刚发现在上面的代码中,FooProperty(公共只读属性)甚至不需要.所以我可以放弃我在上面的代码示例中高亮显示的那条线,但事情仍然正常.我现在更加好奇为什么人们在使用mutable val等等时会如此简单?我错过了重要的事吗?


更新#2:在下面的评论中,Robert Jeppesen提供了一个指向MSDN页面超链接,其中提到了以下内容:

如果你没有遵循这个命名模式 [即.FooFooProperty] ,设计人员可能无法正确报告您的属性,并且属性系统样式应用程序的某些方面可能无法按预期运行.

我将Expression Blend 4放入测试中,发现当公共静态FooProperty完全丢失时,它似乎根本没有受到影响.

Ray*_*rns 8

是的,无论您是否使用公共静态字段,它确实有所不同.但根据您的需求,可能没有显着差异.我将解释WPF本身在哪些方面表现不同,然后提到其他一些可能也存在问题的情况.

如果使用静态属性而不是静态字段,则对XAML解析有影响

实际上注意到你是使用静态属性还是静态字段的WPF本身的唯一部分是XAML解析器,并且它产生差异的唯一情况是在多个级别使用相同的属性名称时.这是因为存在具有匹配名称且以"Property"结尾的静态字段用于消除多个级别上具有相同名称的DependencyProperties之间的歧义.

您将看到一个区别的地方是,如果您使用公共静态属性(或根本没有)定义您的属性,并且祖先类使用公共静态字段具有相同名称的DependencyProperty,则将使用祖先类的属性而不是你的.

例如,假设创建一个具有名为"Language"的DependencyProperty的Control.FrameworkElement已经有一个"语言"DependencyProperty,但只要您遵循标准并使用公共静态字段,那就没关系:您的"语言"属性将优先.但是,如果您使用公共静态属性,您的XAML将最终设置"FrameworkElement.Language"依赖项属性,而不是您的属性.

例如,如果新版本的WPF出现在您的某个基类上定义了新的依赖项属性,则可能会出现问题.例如,如果您使用的是"深度"属性,您已使用静态字段定义,并且.NET Framework 5.0在"Visual"上定义了"深度"属性,则您的应用程序将无法在新版本的.NET Framework上运行.

这可能会产生影响的另一种情况是更改类层次结构时.在这种情况下,WPF会尝试保护您免受版本控制问题的影响,但如果您使用公共静态属性而不是公共静态字段,则其保护会消失.最简单的方案是你写了一个库,人们正在使用你的财产.如果您使用公共静态字段,则编译的应用程序实际上将包含您的类名,因此不会出错.但是如果你使用了公共静态属性(或者根本没有)他们编译的应用程序将使用他们的派生类名称来引用它.因此,如果继承层次结构发生更改或介于其间引入了新属性,则即使在已编译的代码中也可能会影响原始属性.例如,如果出现以下情况,这可能是个问题:

  • YourControl派生自ThirdPartyGrid
  • 当ThirdPartyGrid没有"语言"字段时编写了YourControl,因此编译后的代码引用了FrameworkElement.Language
  • 如果ThirdPartyGrid的供应商添加"语言"依赖项属性,它将不会影响您的应用程序
  • 但是,如果将FrameworkElement.Language定义为公共静态属性,则供应商的添加会破坏您的应用程序

还有一些更为神秘的情况可以带来改变.

对设计师工具的影响

据我所知,如果您使用公共静态属性而不是字段定义属性,或者即使您完全不使用它,Visual Studio和Expression Blend也不会有任何不同的行为,除非它们遇到前面提到的XAML解析器行为.

但是应该注意的是,有许多XAML开发环境,并且由于使用静态字段的模式是如此牢固地建立,它们可能依赖于此.所以这是一个警告.

除了XAML解析之外,对WPF本身的影响

除了XAML解析器之外,WPF的任何部分都不关心您是否已经定义了公共静态属性,字段或根本没有.在每种情况下,您都可以使用完全相同的DependencyProperties.然而:

  1. 我知道并不能保证这一切都是真的,并且
  2. 第三方代码很容易依赖它