WPF之依赖属性
简而言之,依赖属性就是一种可以自己没有值,并能通过使用Binding从数据源获得值(依赖在别人身上)的属性。而拥有依赖属性的对象被称为依赖对象。
与传统的CLR属性和面向对象思想相比依赖属性有很多新颖之处:
- 节省实例对内存的开销。因为属性值在其他对象那里,而不在使用依赖属性的对象这里,所以节省了内存开销。
- 属性值可以通过Binding依赖在其他对象上。
依赖属性对内存的使用方式
传统的.NET开发中,一个对象所占用的内存控件在调用new操作符进行实例化的时候就已经决定了,而WPF允许对象在被创建的时候并不包含用于储存数据的控件,只保留在需要时候能够获得默认值,借用其他对象数据或者分配空间的能力,这种对象就称为依赖对象,而它这种实时获取数据的能力则依靠依赖属性来实现,注意依赖对象不是数据产生的对象,而是具备获取其他对象的数据的能力的对象。
需要注意的是ItemSource所绑定的属性,必须同时具备{get;set;},如果不允许用户修改,则{get;private set},但必须同时具备,否则绑定的UI元素不会显示名称.
在WPF中,依赖对象的概念被DependencyObject
类所实现,依赖属性的概念被DependencyProperty
类所实现。DependencyObject具有GetValue和SetValue两个方法,DependencyProperty
必须以DependencyObject
为宿主,以这两个方法来进行写入与读取。
public class DependencyOobject:DispatcherObject{
public object GetValue(DependencyPropertyy dp)//从DependencyProperty对象获取数据
{
...///
}
public void SetValue(DependencyProperty dp,object value)
{
...///
}
}
DependencyObject
是WPF系统中相当底层的一个基类,所有UI控件都是依赖对象。
例子:
<StackPanel Background="LightBlue">
<TextBox x:Name="textBox1" BorderBrush="Black" Margin="5"/>
<TextBox x:Name="textBox2" BorderBrush="Black" Margin="5"/>
<Button x:Name="btn" Content="OK" Click="btn_Click"/>
</StackPanel>
public partial class MainWindow : Window
{
Student stu;
public MainWindow()
{
InitializeComponent();
stu = new Student();
Binding binding = new Binding("Text") { Source = this.textBox1 };
stu.SetBinding(Student.NameProperty, binding);
textBox2.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu });
}
private void btn_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(stu.Name);
}
}
public class Student : DependencyObject
{
//注册依赖属性
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(Student));
//CLR包装属性
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
//SetBinding包装
public BindingExpressionBase SetBinding(DependencyProperty dp,BindingBase binding)
{
return BindingOperations.SetBinding(this, dp, binding);
}
}
简单总结下创建依赖对象,使用依赖属性的三部曲:
-
继承
DependancyObject
类 -
在依赖对象内用
DependancyProperty.Register
方法注册依赖属性 -
用CLR属性进行包装,结合依赖对象的
SetValue
和GetValue
方法。
附加属性
附加属性将的是一个属性本来不属于某个对象,但由于某种需求而被后来附加上。也就是把对象放入一个特定的环境后哦,对象才具有的属性。
Demo:
<StackPanel Background="LightBlue">
<Button x:Name="btn" Content="OK" Click="btn_Click"/>
</StackPanel>
namespace MessagePump
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btn_Click(object sender, RoutedEventArgs e)
{
Human human = new Human();
School.SetGrade(human, 6);
int grade = School.GetGrade(human);
MessageBox.Show(grade.ToString());
}
}
public class School : DependencyObject
{
//通过GetGrade、SetGrade,调用Human的SetValue和GetValue方法,存储依赖变量的值。
public static int GetGrade(DependencyObject obj)
{
return (int)obj.GetValue(GradeProperty);
}
public static void SetGrade(DependencyObject obj, int value)
{
obj.SetValue(GradeProperty, value);
}
// Using a DependencyProperty as the backing store for GradeProperty. This enables animation, styling, binding, etc...(注册依赖变量)
public static readonly DependencyProperty GradeProperty =
DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(School), new PropertyMetadata(0));
}
class Human : DependencyObject
{
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)