Wpf 简明教程

WPF - Dependency Properties

在 WPF 应用程序中,依赖属性是一种扩展 CLR 属性的特定类型属性。它利用了 WPF 属性系统中可用的特定功能。

定义依赖属性的类必须继承自 DependencyObject 类。XAML 中使用的许多 UI 控件类都继承自 DependencyObject 类并且它们支持依赖属性,例如,Button 类支持 IsMouseOver 依赖属性。

以下 XAML 代码创建一个具有某些属性的按钮。

<Window x:Class = "WPFDependencyProperty.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFDependencyProperty"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <Button  Height = "40" Width = "175" Margin = "10" Content = "Dependency Property">
         <Button.Style>
            <Style TargetType = "{x:Type Button}">
               <Style.Triggers>

                  <Trigger Property = "IsMouseOver" Value = "True">
                     <Setter Property = "Foreground" Value = "Red" />
                  </Trigger>

               </Style.Triggers>
            </Style>
         </Button.Style>
      </Button>
   </Grid>

</Window>

XAML 中的 x:Type 标记扩展具有类似 C# 中 typeof() 的功能。当指定将采用对象类型的属性时使用此功能,例如 <Style TargetType = "{x:Type Button}">。

当编译并执行上述代码时,你将获得以下 MainWindow 。当鼠标位于按钮上方时,它会更改按钮的前景色。当鼠标离开按钮时,它会变回其原始颜色。

dependency property

Why We Need Dependency Properties

当你将其用于你的应用程序时,依赖属性会为你提供各种好处。依赖属性在以下情况下可用于 CLR 属性:

  1. 如果你想设置样式

  2. 如果你想数据绑定

  3. 如果你想使用资源(静态资源或动态资源)进行设置

  4. 如果你想支持动画

基本上,依赖属性提供了许多使用 CLR 属性无法获得的功能。

dependency properties 和其他 CLR properties 之间的主要区别如下所列:

  1. CLR 属性可以使用 gettersetter 直接从类的私有成员中读/写。相比之下,依赖属性不存储在本地对象中。

  2. 依赖属性存储在 DependencyObject 类提供的键/值成对的词典中。它还节省了许多内存,因为它在更改时存储属性。它也可以在 XAML 中进行绑定。

Custom Dependency Properties

在 .NET framework 中,还可以定义自定义依赖属性。请按照以下步骤在 C# 中定义自定义依赖属性。

  1. 使用系统调用 register 声明并注册你的 dependency property

  2. 为该属性提供 settergetter

  3. 定义一个 static handler ,该 static handler 将处理全局发生的任何更改。

  4. 定义一个 instance handler ,该 instance handler 将处理发生在特定实例上的任何更改。

以下 C# 代码定义了一个依赖属性来设置用户控件的 SetText 属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3 {
   /// <summary>
      /// Interaction logic for UserControl1.xaml
   /// </summary>

   public partial class UserControl1 : UserControl {

      public UserControl1() {
         InitializeComponent();
      }

      public static readonly DependencyProperty SetTextProperty =
         DependencyProperty.Register("SetText", typeof(string), typeof(UserControl1), new
            PropertyMetadata("", new PropertyChangedCallback(OnSetTextChanged)));

      public string SetText {
         get { return (string)GetValue(SetTextProperty); }
         set { SetValue(SetTextProperty, value); }
      }

      private static void OnSetTextChanged(DependencyObject d,
         DependencyPropertyChangedEventArgs e) {
         UserControl1 UserControl1Control = d as UserControl1;
         UserControl1Control.OnSetTextChanged(e);
      }

      private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) {
         tbTest.Text = e.NewValue.ToString();
      }
   }
}

这是 TextBlock 被定义为用户控件的 XAML 文件,并通过 SetText 依赖属性将 Text 属性分配给它。

下面的 XAML 代码创建了一个用户控件并初始化了它的 SetText 依赖属性。

<Window x:Class = "WpfApplication3.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:views = "clr-namespace:WpfApplication3"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <views:UserControl1 SetText = "Hellow World"/>
   </Grid>

</Window>

让我们运行该应用程序。你可以立即观察到在我们的 MainWindow 中,用户控件的依赖属性已经成功用作 Text。

dependency property for user