建设工程专业承包交易中心网站,拉人头最暴利的app,西安有什么好玩的游乐园,专业网站制作设说明#xff1a;本文是介绍WPF中的依赖属性功能#xff0c;如果对依赖属性已经有了解了#xff0c;可以浏览后面的文章。 为什么要介绍依赖属性
在WPF的数据绑定中#xff0c;密不可分的就是依赖属性。而MVVM又是跟数据绑定紧密相连的#xff0c;所以在学习MVVM之前…说明本文是介绍WPF中的依赖属性功能如果对依赖属性已经有了解了可以浏览后面的文章。 为什么要介绍依赖属性
在WPF的数据绑定中密不可分的就是依赖属性。而MVVM又是跟数据绑定紧密相连的所以在学习MVVM之前很有必要先学习一下依赖属性。 依赖属性(Depencency Property)是什么
先来看看MSDN上的解释
WPF提供一组服务这些服务可用于扩展类型的属性的功能。 这些服务统称为 WPF 属性系统。 由 WPF 属性系统提供支持的属性称为依赖属性。
通俗点来说WPF的依赖属性就是在.NET属性的基础上进行的扩展。它除了具备.NET属性的功能之外还具备一些其它的扩展功能如值验证、默认值、值修改时的回调、转换器等。 我们先来看看.NET属性也就是平常我们在C#中使用的属性 1 public class CLRProperty2 {3 private int id;4 5 public int Id6 {7 get id;8 set id value;9 }
10 } 再来看看依赖属性
以Button控件的Content属性为例 1 public static readonly DependencyProperty ContentProperty DependencyProperty.Register(Content, typeof(object), typeof(ContentControl), new FrameworkPropertyMetadata((object)null, (PropertyChangedCallback)OnContentChanged));2 3 public object Content4 {5 get6 {7 return GetValue(ContentProperty);8 }9 set
10 {
11 SetValue(ContentProperty, value);
12 }
13 } 可以看到它也有一个get和set即.NET的属性包装器但是没有私有变量而是通过GetValue和SetValue来完成取值和赋值。
依赖属性在使用上依赖属性和.NET属性无异
例如有一个Button控件命名为btn_Ok我们可以在XAML中直接设置依赖属性的值
1 Button Namebtn_Ok ContentHelloWorld/Button 也可以在后台代码中设置
1 btn_Ok.Content HelloWorld; 如何创建依赖属性
大多数在使用WPF原生控件的情况下我们都是使用依赖属性而非创建它。但是在自定义控件时可能会需要用到依赖属性功能。
依赖属性对象不能直接被实例化因为它没有公开的构造函数只能通过DependencyProperty.Register()方法创建实例。 我们这里以自定义一个MyButton控件为例。 1、定义表示属性的对象
注意这里使用了static readonly关键字且对象命名时后面都加上Property。
1 public static readonly DependencyObject ImageProperty; 2、注册依赖属性
1 ImageProperty DependencyProperty.Register(Image, typeof(ImageSource), typeof(MyButton),new PropertyMetadata(null, OnImagePropertyChanged)); DependencyProperty.Register函数支持多种重载下面这是一种比较常用的重载。
1 public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata); 下面来介绍一下它各个参数的作用
name这个参数用于指定.NET属性包装器的名称
propertyType指明依赖项属性存储什么类型的值这里是ImageSource类型代表图像数据
ownerType指明此依赖属性的宿主是什么类型这里是MyButton
typemetaData指定此依赖属性的元数据元数据定义依赖属性在应用于特定类型时的某些行为方面包括默认值、值更改时的回调等。上面的代码中typeMetadata的第一个参数代表依赖属性的默认值设置为null第二个参数是在值更改时的回调函数这里是调用OnImagePropertyChanged函数。 3、添加属性包装器
1 public ImageSource Image
2 {
3 get (ImageSource)GetValue(ImageProperty);
4 set SetValue(ImageProperty, value);
5 } 4、使用依赖属性
XAML
1 local:MyButton x:Namebtn_Ok Imagelogo.jpg/ 后台代码
1 this.btn_Ok.Image new BitmapImage(new Uri(logo.jpg, UriKind.Relative)); 附加属性(Attached Property)
附加属性是一种特殊的依赖属性。
来看看MSDN上的解释
附加属性是一个 XAML概念。 附加属性允许为派生自 DependencyObject 的任何 XAML 元素设置额外的属性/值对即使该元素未在其对象模型中定义这些额外的属性。 额外的属性可进行全局访问。 附加属性通常定义为没有常规属性包装器的依赖属性的专用形式。
通俗点来说就是这个属性并不属于某个元素但是通过附加属性可以设置上去。
附加属性在定义时是被定义到应用的那个类而非使用附加属性的那个类。 一个简单的例子例如一个Button控件在被设计出来以后设计者也不知道它以后会被用于哪个布局容器可能是Canvas也可能 是Grid。
这个时候附加属性的作用就体现出来了
当这个Button被放在Grid里时就为它附加上Grid.Row和Grid.Column属性。
当这个Button被放在Canvas里时就为它附加上Canvas.Left和Canvas.Top属性。
所以Grid.Row和Column是定义在Grid类中而Canvas.Left和Canvas.Top是被定义在Canvas中。这一点跟前面的依赖属性有区别。 下面我们看一下附加属性代码结构以Grid.Row为例
Grid.Row附加属性的定义如下 1 public static readonly DependencyProperty RowProperty DependencyProperty.RegisterAttached(Row, typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, OnCellAttachedPropertyChanged), IsIntValueNotNegative);2 3 public static int GetRow(UIElement element)4 {5 if (element null)6 {7 throw new ArgumentNullException(element);8 }9
10 return (int)element.GetValue(RowProperty);
11 }
12
13 public static void SetRow(UIElement element, int value)
14 {
15 if (element null)
16 {
17 throw new ArgumentNullException(element);
18 }
19
20 element.SetValue(RowProperty, value);
21 } 如何创建附加属性
这里我们以为每个控件增加一个Id依赖属性为例这个属性仅做演示 1、定义表示属性的对象
1 public static readonly DependencyProperty IdProperty; 2、注册附加属性
1 IdProperty DependencyProperty.RegisterAttached(Id, typeof(int), typeof(ControlExtension)); 如果要设置默认值及值验证可以参考这里这里暂时不做详细的介绍后面有时间再补上。 3、添加属性包装器
这里和依赖属性的属性包装器不太一样这里变成了Getxxx和Setxxx函数的形式。 1 public static int GetId(DependencyObject dependencyObject)
2 {
3 return (int)dependencyObject.GetValue(IdProperty);
4 }
5
6 public static void SetId(DependencyObject dependencyObject,int value)
7 {
8 dependencyObject.SetValue(IdProperty, value);
9 } 4、使用附加属性
XAML赋值 1 Window x:ClassIntroductionToAttachedProperty.MainWindow2 xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation3 xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml4 xmlns:dhttp://schemas.microsoft.com/expression/blend/20085 xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/20066 xmlns:localclr-namespace:IntroductionToAttachedProperty7 mc:Ignorabled8 TitleMainWindow Height450 Width800 LoadedWindow_Loaded9 Grid Namegrid local:ControlExtension.Id100
10
11 /Grid
12 /Window 在后台代码中获取附加属性的值
1 private void Window_Loaded(object sender, RoutedEventArgs e)
2 {
3 MessageBox.Show(ControlExtension.GetId(this.grid).ToString());
4 } 在后台代码中赋值
1 ControlExtension.SetId(this.grid, 100); 总结
WPF的属性在MVVM模式开发中非常关键所以有必要了解清楚。本文仅介绍了依赖属性和附加属性的基础概念对于掌握MVVM模式基础开发来说已经够用。
本文不包括依赖属性内存存储方式、属性取值优先级、属性默认值、属性值更改回调、属性验证等概念在后面的文章中再进行补充。 参考资料
https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/properties/dependency-properties-overview?viewnetdesktop-8.0sourcerecommendations 示例代码
https://github.com/zhaotianff/WPF-MVVM-Beginner/tree/main/2_DependencyProperty