一、什么是依赖属性

依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值。依赖属性可支持WPF中的样式设置、数据绑定、继承、动画及默认值。

将所有的属性都设置为依赖属性并不总是正确的解决方案,具体取决于其应用场景。有时,使用私有字段实现属性的典型方法便能满足要求。MSDN中给出了下面几种应用依赖属性的场景:

1. 希望可在样式中设置属性。

2. 希望属性支持数据绑定。

3. 希望可使用动态资源引用设置属性。

4. 希望从元素树中的父元素自动继承属性值。

5. 希望属性可进行动画处理。

6. 希望属性系统在属性系统、环境或用户执行的操作或者读取并使用样式更改了属性以前的值时报告。

7. 希望使用已建立的、WPF 进程也使用的元数据约定,例如报告更改属性值时是否要求布局系统重新编写元素的可视化对象。

二、依赖属性的特点

1、属性变更通知

无论什么时候,只要依赖属性的值发生改变,wpf就会自动根据属性的元数据触发一系列的动作,这些动作可以重新呈现UI元素,也可以更新当前的布局,刷新数据绑定等等,这种变更的通知最有趣的特点之一就是属性触发器,它可以在属性值改变的时候,执行一系列自定义的动作,而不需要更改任何其他的代码来实现。通过下面的示例来演示属性变更通知

示例:当鼠标移动到Button按钮上面时,文字的前景色变为红色,离开时变为默认颜色黑色,采用传统方式和依赖属性两种方式实现:

(1)、使用传统方式实现,在Button按钮上定义MouseEnter和MouseLeave两个事件,分别处理鼠标移动到按钮上面和离开,XAML界面代码:

1 <Window x:Class="WpfDemo.MainWindow"
2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4         Title="Grid面板" Height="237" Width="525" WindowStartupLocation="CenterScreen">
5     <Grid >
6         <Button Height="30" Width="200" MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave" >鼠标移动到上面,前景色变为红色</Button>
7     </Grid>
8 </Window>

C#后台代码实现:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15
16 namespace WpfDemo
17 {
18     /// <summary>
19     /// MainWindow.xaml 的交互逻辑
20     /// </summary>
21     public partial class MainWindow : Window
22     {
23         public MainWindow()
24         {
25             InitializeComponent();
26         }
27
28         /// <summary>
29         /// 鼠标移动到按钮上面
30         /// </summary>
31         /// <param name="sender"></param>
32         /// <param name="e"></param>
33         private void Button_MouseEnter(object sender, MouseEventArgs e)
34         {
35             Button btn = sender as Button;
36             if (btn != null)
37             {
38                 btn.Foreground = Brushes.Red;
39             }
40         }
41
42         /// <summary>
43         /// 鼠标离开按钮
44         /// </summary>
45         /// <param name="sender"></param>
46         /// <param name="e"></param>
47         private void Button_MouseLeave(object sender, MouseEventArgs e)
48         {
49             Button btn = sender as Button;
50             if (btn != null)
51             {
52                 btn.Foreground = Brushes.Black;
53             }
54         }
55     }
56 }

(2)使用依赖属性实现,XAML界面代码:

 1 <Window x:Class="WpfDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="Grid面板" Height="237" Width="525" WindowStartupLocation="CenterScreen">
 5     <Grid >
 6         <Button Height="30" Width="200">鼠标移动到上面,前景色变为红色
 7             <Button.Style>
 8                 <Style TargetType="Button">
 9                     <Style.Triggers>
10                         <Trigger Property="IsMouseOver" Value="true">
11                             <Setter Property="Foreground" Value="Red"></Setter>
12                         </Trigger>
13                     </Style.Triggers>
14                 </Style>
15             </Button.Style>
16         </Button>
17     </Grid>
18 </Window>

使用上面的两种方式都可以实现Button按钮的前景色改变,效果如下:

在判断属性IsMouseOver的值为false的时候,自动将Foreground的值改为之前的值,因此就不需要写IsMouseOver的值为false的时候,将Foreground的值改为Black。

2、属性值继承

是指属性值自顶向下沿着元素树进行传递。

 1 <Window x:Class="WpfDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="依赖属性" Height="237" Width="525" FontSize="18" WindowStartupLocation="CenterScreen">
 5     <Grid >
 6         <StackPanel>
 7             <TextBlock>我使用的是继承的fontsize</TextBlock>
 8             <TextBlock FontSize="11">我使用的是自己的fontsize</TextBlock>
 9         </StackPanel>
10     </Grid>
11 </Window>

界面运行效果:

3、节省内存空间

依赖属性和CLR属性在内存的使用上是截然不同的,每个CLR属性都包含一个非static的字段,因此当我们实例化一个类型的时候,就会创建该类型所拥有的所有CLR属性,也就是说一个对象所占用的内存在调用new操作进行实例化的时候就已经决定了、而wpf允许对象在创建的时候并不包含用于存储数据的空间,只保留在需要用到数据的时候能够获得该默认值,即用其他对象数据或者实时分配空间的能力。

三、如何自定义依赖属性

1、声明依赖属性变量。依赖属性的声明都是通过public static来公开一个静态变量,变量的类型必须是DependencyProperty
2、在属性系统中进行注册。使用DependencyProperty.Register方法来注册依赖属性,或者是使用DependencyProperty.RegisterReadOnly方法来注册
3、使用.NET属性包装依赖属性

在类上实现属性时,只要该类派生自 DependencyObject,便可以选择使用 DependencyProperty 标识符来标示属性,从而将其设置为依赖属性。其语法如下:

 1 public static DependencyProperty TextProperty;
 2        TextProperty =
 3        DependencyProperty.Register("Text", //属性名称
 4        typeof(string), //属性类型
 5        typeof(TestDependencyPropertyWindow), //该属性所有者,即将该属性注册到那个类上
 6        new PropertyMetadata("")); //属性默认值
 7
 8 public string Text
 9 {
10    get { return (string)GetValue(TextProperty); }
11    set { SetValue(TextProperty, value); }
12 }

示例:自定义一个依赖属性,界面包括一个TextBox和TextBlock,TextBlock上面字体的前景色随TextBox里面输入的颜色而改变,如果TextBox里面输入的值可以转换成颜色,TextBlock字体的前景色会显示输入的颜色值,如果不能转换,显示默认的前景色。

1、在当前项目里面添加一个WPF版的用户控件,命名为“MyDependencyProperty”,在MyDependencyProperty.xaml.cs文件里面自定义一个依赖属性:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15
16 namespace WpfDemo
17 {
18     /// <summary>
19     /// MyDependencyProperty.xaml 的交互逻辑
20     /// </summary>
21     public partial class MyDependencyProperty : UserControl
22     {
23         public MyDependencyProperty()
24         {
25             InitializeComponent();
26         }
27
28         //1、声明依赖属性变量
29         public static readonly DependencyProperty MyColorProperty;
30
31         //2、在属性系统中进行注册
32         static MyDependencyProperty()
33         {
34             MyColorProperty = DependencyProperty.Register("MyColor", typeof(string), typeof(MyDependencyProperty),
35                 new PropertyMetadata("Red", (s, e) =>
36                 {
37                     var mdp = s as MyDependencyProperty;
38                     if (mdp != null)
39                     {
40                         try
41                         {
42                             var color = (Color)ColorConverter.ConvertFromString(e.NewValue.ToString());
43                             mdp.Foreground = new SolidColorBrush(color);
44                         }
45                         catch
46                         {
47                             mdp.Foreground = new SolidColorBrush(Colors.Black);
48                         }
49                     }
50
51                 }));
52         }
53
54         //3、使用.NET属性包装依赖属性:属性名称与注册时候的名称必须一致,
55         //即属性名MyColor对应注册时的MyColor
56         public string MyColor
57         {
58             get
59             {
60                 return (string)GetValue(MyColorProperty);
61             }
62             set
63             {
64                 SetValue(MyColorProperty, value);
65             }
66         }
67     }
68 }

快速定义依赖属性的快捷方式:

输入propdp,连续按两下Tab健,自动生成定义依赖属性的语法。和输入cw连续按两下Tab健,自动生成Console.Write()一样。

1 public int MyProperty
2         {
3             get { return (int)GetValue(MyPropertyProperty); }
4             set { SetValue(MyPropertyProperty, value); }
5         }
6
7         // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
8         public static readonly DependencyProperty MyPropertyProperty =
9             DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));

2、在MyDependencyProperty.xaml里面添加一个TextBlock

 1 <UserControl x:Class="WpfDemo.MyDependencyProperty"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6              mc:Ignorable="d"
 7              d:DesignHeight="300" d:DesignWidth="300">
 8     <Grid>
 9         <TextBlock>我是自定义的依赖属性</TextBlock>
10     </Grid>
11 </UserControl>

3、在MainWindow.xaml里面引用新创建的用户控件,并添加一个TextBox,用于输入颜色值,并将自定义的依赖属性MyColor绑定到TextBox

 1 <Window x:Class="WpfDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:p="clr-namespace:WpfDemo"
 5         Title="依赖属性" Height="237" Width="525" WindowStartupLocation="CenterScreen">
 6     <Grid >
 7         <StackPanel>
 8             <TextBox Name="tbColor"></TextBox>
 9             <p:MyDependencyProperty MyColor="{Binding Path=Text,ElementName=tbColor}" ></p:MyDependencyProperty>
10         </StackPanel>
11     </Grid>
12 </Window>

在设计界面显示的效果:

4、程序运行效果:

在TextBox里面输入正确的颜色值,前景色会显示为当前输入的颜色:

在TextBox里面输入错误的颜色值,前景色会显示为默认颜色:

WPF教程:依赖属性相关推荐

  1. WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性

    原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...

  2. WPF 中依赖属性的继承(Inherits)

    WPF中依赖属性的值是是可以设置为可继承(Inherits)的,这种模式下,父节点的依赖属性会将其值传递给子节点.例如,数据绑定中经常使用的DataContextProperty: var host ...

  3. WPF的依赖属性和附加属性(用法解释较全)

    转:https://www.cnblogs.com/zhili/p/WPFDependencyProperty.html 一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己 ...

  4. WPF之依赖属性和附加属性

     参考资料: 一站式WPF--依赖属性(DependencyProperty)一 一站式WPF--依赖属性(DependencyProperty)二         依赖属性之我见: 这两篇文章介绍的 ...

  5. WPF教程UpdateSourceTrigger属性

    在前面的文章我们看到,TextBox中的变化并不是立即传递到源,而是在TextBox失去焦点后,源才更新.这种表现由绑定中的UpdateSourceTrigger属性来控制.它的默认值是Default ...

  6. WPF整理-为User Control添加依赖属性

    WPF整理-为User Control添加依赖属性 原文:WPF整理-为User Control添加依赖属性 依赖属性 ".NET properties are nothing more t ...

  7. WPF快速入门系列(2)——深入解析依赖属性

    一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列.尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF.今天继续分享WPF中一个最 ...

  8. [UWP]依赖属性2:使用依赖属性

    原文:[UWP]依赖属性2:使用依赖属性 5. 完整的自定义依赖属性 5.1 定义 /// <summary> /// 标识 Title 依赖属性. /// </summary> ...

  9. javascript中依赖属性(Dependency Property)的实现

    好久没在首页发点东西了,昨天在js上依照wpf中依赖属性的思想尝试写了基本的功能.这里拿出来与大家分享 Demo1 注册依赖属性 step1 定义一个函数 function Person() {thi ...

  10. SilverlightWPF依赖属性DependencyProperty讲解

    作者:周永恒  出处:http://www.cnblogs.com/Zhouyongh   本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

最新文章

  1. 干货丨机器学习?人工智能?还在傻傻分不清楚?
  2. 2、前端环境搭建(19.04.12)
  3. 直播 | ACL 2021论文解读:提升预训练语言模型实体与关系理解的统一框架
  4. Logistic回归与梯度上升算法
  5. MVVM模式下实现拖拽
  6. Hadoop初次接触后感
  7. 路由器与计算机IP配置,电脑的IP地址和DNS等参数如何设置
  8. spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
  9. 太阳跟踪 matlab,太阳能和最大功率点跟踪
  10. 写好软文标题的10个方式
  11. win7怎么查找网络上的计算机,Win7系统无法查看工作组计算机如何解决? Win7系统查看工作组计算机的方法...
  12. 一个twitter puddles的算法实现
  13. C语言的那些小秘密之异常处理
  14. 唯美的英文短文!!!
  15. vue html模板递归,vue使用递归组件实现多级列表
  16. vue前端使用jsencrypt RSA 加解密插件
  17. 计算机一级msoffice考试操作题教程,2014年计算机一级考试MSOffice第三章考点解析 10...
  18. 使用 es6 class类创建对象 在其他页面 用vue引用报错 is not a constructor
  19. Live mail 配置Gmail邮件收发
  20. 风色幻想ol服务器文件,开个魔导帖吧,总结下GF52的经验,服务器好像down了,写给新手,顺便问...

热门文章

  1. 做了三年Java,java简历包装项目经验
  2. javascript html注释,javascript html注释
  3. dell保修及其升级3CC
  4. 机器人工程毕业设计☞开题报告
  5. 计算机-国家精品课程-推荐
  6. 三对角矩阵的存储和获取(C++版)
  7. 三相异步电机----电机公式(三)
  8. 【IT】QTTabBar使用
  9. Git服务器更换IP
  10. php gb2312转big5 函数