深入了解 |WPF的DependencyProperty

今天我们将深入了解WPF(Windows Presentation Foundation)的一个核心概念:DependencyProperty。DependencyProperty是最能解释WPF特性的重要元素之一,在本文中,我们将简称其为DP。

DependencyProperty概览

DP的目的是将普通属性以静态方式注册并使用。在WPF中,大多数UI属性都使用DependencyProperty,这使得可以实现可绑定的属性特性。这样的属性例如ToggleButton的IsChecked。这些属性通过DependencyProperty.Register方法进行注册,在构造过程中由内部的DependencyProperty实例进行管理。

public static readonly DependencyProperty IsCheckedProperty =
    DependencyProperty.Register(
        "IsChecked",
        typeof(bool?),
        typeof(ToggleButton),
        new FrameworkPropertyMetadata(...,
            new PropertyChangedCallback(OnIsCheckedChanged)));

public bool? IsChecked
{
    get => ...
    set => ...
}

private static void OnIsCheckedChanged(DependencyObject d,    
    DependencyPropertyChangedEventArgs e)
{
    ToggleButton button = (ToggleButton)d;
    bool? oldValue = (bool?) e.OldValue;
    bool? newValue = (bool?) e.NewValue;
    ...
}

DependencyProperty的结构

查看DependencyProperty的结构,它主要由三个元素组成:

  • 静态的DependencyProperty(通过Register进行注册)
  • bool? IsChecked(属性特性)
  • 静态的OnIsCheckedChanged(回调方法)

在这里,回调方法是可选的,根据使用目的可实现或不实现。

Register注册

由于DependencyProperty类是通过sealed访问修饰符封闭的,并且构造函数也被设置为private,因此只能在Register方法内部创建DP实例。这样的限制意味着创建DP的唯一方法是通过DependencyProperty.Register(或Attached)调用。在构造过程中,它会将自身添加到名为RegisteredPropertyList的静态集合对象中,从而能自然地收集并管理所有DP。

Property声明

使用DP的属性看起来像普通属性,但其内部的get和set没有实际使用的字段。相反,它们使用GetValue和SetValue方法。

public bool IsChecked
{
    get => (bool)GetValue(ContentNameProperty);
    set => SetValue(ContentNameProperty, value);
}

GetValue()和SetValue()方法可以通过DependencyObject使用。所有的WPF UI类都继承自DependencyObject,因此可以在任何地方注册DP并配置属性。

内部字段管理

实际上,在注册DP时,内部字段的管理已经准备好了。因此,归根结底,DependencyProperty内部管理一个(静态的)字段,并通过GetValue/SetValue方法提供字段的使用,然后通过属性来使用这个值。

依赖属性的概念

DP是通过DependencyProperty和DependencyObject以及内部逻辑,将所有的值以静态方式进行管理。这样以静态方式管理值的原因是,当DP自身没有值时,它会从VisualTree的层次结构中,比自己位置更高的最近的直接父控件继承DP值。由于这样的结构,可以期望在内存管理方面具有效率,并且对性能也有好处。

举个例子,假设在以下的WPF控件中使用了FontSize DP属性。

<Window FontSize="15">
    <StackPanel FontSize="15">
        <Button FontSize="15"/>
        <TextBlock FontSize="15"/>
        <MyCustomControl FontSize="15"/>
    </Grid>
</Window>


如果除了Window之外的所有控件都移除了FontSize属性,情况就会发生变化。

<Window FontSize="15">
    <StackPanel>
        <Button/>
        <TextBlock/>
        <MyCustomControl/>
    </Grid>
</Window>

这样的设计使得WPF控件在不同层级之间能够更有效地共享和继承属性值,同时还能减少冗余和提高性能。

在这种情况下,内部实际上只会有一个Window FontSize的值,而不是原来的5个。那么其他四个控件的FontSize值会处于Empty状态吗?答案是不会。因为DP会继承其父控件的值,所以从static Field继承的DP属性会表现得像是有自己的值一样。这就是依赖属性(DependencyProperty)的核心概念。

因此,在WPF中,所有控件都具有DataContext DP属性。除非显式更改了自己的DataContext,否则它们会使用其上级控件的DataContext。这样一来,只需在上级控件中设置一次DataContext,子控件就会自动参考并使用上级控件的DataContext。正是由于这样实现的依赖属性(DP)功能,WPF中的数据绑定能够如此强大地工作。

这种设计不仅简化了数据绑定和属性设置的逻辑,还使得在WPF应用程序的整体架构中,从上至下都能更加高效和灵活地管理状态和数据流,大大提高了开发效率和运行性能。

<Window DataContext="{Binding MyViewModel}">
    <StackPanel>
        <Button Command="{Binding MyCommand}"/>
        <TextBlock Text="{Binding MyText}"/>
        <MyCustomControl SomeProperty="{Binding MyProperty}"/>
    </Grid>
</Window>

在上面的例子中,StackPanel、Button、TextBlock、MyCustomControl都会引用其上级控件,即Window的DataContext。因此,在各个控件中无需单独设置DataContext,就能实现与ViewModel中的MyCommand、MyText、MyProperty的绑定。

依赖属性(DependencyProperty,简称DP)具有诸如继承、提供默认值、更改通知、数据绑定等特性,这些特性都极大地贡献了WPF的可用性和性能提升。希望通过本文,大家能理解DependencyProperty的基本概念、结构和工作原理。如果大家想了解更深入的内容,建议查找与DependencyProperty相关的资料,这将对大家有所帮助。
 

  • 26
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
WPF(Windows Presentation Foundation)是一种用于创建Windows桌面应用程序的技术。深入浅出WPF原码可以让我们更好地理解WPF的工作原理和实现机制。 在深入研究WPF原码之前,我们首先需要了解WPF的基本概念和架构。WPF基于XAML语言(可扩展应用程序标记语言),通过定义UI元素的层次结构和属性来构建界面。WPF通过使用可视树和逻辑树来描述应用程序的界面和行为。 深入WPF原码的过程中,我们可以学习到WPF的重要组件和类,例如UIElement、DependencyObject、DependencyProperty和Visual等。UIElement是WPF控件的基类,通过继承和重写UIElement类的方法,我们可以实现自定义的控件。DependencyObject是WPF中属性系统的基类,通过定义依赖属性(DependencyProperty),我们可以实现属性的绑定、动画和数据验证等功能。Visual则是WPF中用于可视化呈现的基类,WPF的可视化树就是由一系列的Visual对象组成。 深入研究WPF原码有助于我们了解WPF是如何处理事件、布局、绘图和渲染等方面的。通过阅读WPF原码,我们可以研究WPF内部实现的细节和机制,如布局系统、渲染管线、命中测试和动画系统等。这些知识对于我们在实际开发中更好地使用和优化WPF应用程序非常有价值。 总之,深入浅出WPF原码是一个学习WPF技术的重要途径,通过理解WPF的内部工作原理,我们可以更好地运用WPF创建出高效、功能强大的Windows桌面应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值