• 6.WPF属性


    属性

    依赖属性

    依赖属性就是一种自己可以没有值,并能通过Binding从数据源获取值的属性。拥有依赖属性的对象被称为依赖对象。

    传统开发中,一个对象占用的内存空间在使用new进行实例化的时候已经确定了,而WPF允许对象在创建的时候不包含用于存储数据的空间,而是拥有在需要用到数据的时候能够获取默认值、借用其他对象数据或实时分配空间的能力。这种对象叫做依赖对象,这种获取数据的能力叫做依赖属性。

    依赖对象要由DependencyObject来实现,该类中具有GetValue和SetValue方法,这两个方法都是以DependencyProperty对象为参数。

    public object GetValue(DependencyProperty dp);
    public void SetValue(DependencyProperty dp, object value);
    
    • 1
    • 2

    依赖属性的声明和使用

    • 依赖属性的使用
    <StackPanel>
        <TextBox x:Name="txt1" Margin="5"/>
        <TextBox x:Name="txt2" Margin="5"/>
        <Button x:Name="btn" Content="OK" Margin="5" Click="Btn_Click"/>
    StackPanel>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class Student : DependencyObject
    {
        //参数1:指明以哪个属性作为依赖属性的包装器,此处使用Name属性作为依赖属性的包装器
        //参数2:指明依赖属性存储什么类型的值
        //参数3:指明宿主类型,这将依赖属性和依赖对象关联到了一起
        public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));
    }
    
    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        Student su = new Student();
        su.SetValue(Student.NameProperty, this.txt1.Text);//将su的依赖属性绑定到txt1.Text上
        txt2.Text = (string)su.GetValue(Student.NameProperty);//获得su的依赖属性
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 依赖属性的包装器
    public class Student : DependencyObject
    {
        //参数1:指明以哪个属性作为依赖属性的包装器,此处使用Name属性作为依赖属性的包装器
        //参数2:指明依赖属性存储什么类型的值
        //参数3:指明宿主类型,这将依赖属性和依赖对象关联到了一起
        public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));
    
    
        //Name属性  作为NameProperty依赖属性的包装器,没有该包装器依赖属性仍能正常工作
        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);
        }
    }
    
    //实现了上面的包装,就可以这样写
    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        Student su = new Student();
        su.SetBinding(Student.NameProperty, new Binding("Text") { Source = txt1 });
        txt2.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = su });//Name是包装器
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N2uhPZgn-1667550843639)(6.属性.assets/image-20221104153546791.png)]

    尽管上面的Student类没有实现INotifyPropertyChanged接口,但是属性值发生改变时与之关联的Binding对象依然可以得到通知,依赖属性默认带有这样的功能。

    可以使用propdp在vs中快速定义依赖属性代码段

    附加属性

    附加属性就是一个属性本来不属于某个对象,但是把这个对象放到特定环境后(宿主)会新增这个属性。

    比如TextBox只有放在Grid里面,Grid.Column才会生效

    附加属性的声明和使用

    附加属性的本质就是依赖属性,两者仅仅在包装器上有一些区别。

    案例:人放在学校,才会有年级和班级,说明年级和班级是附加属性,宿主是学校。

    public class School : DependencyObject
    {
    
        //和依赖属性的不同点1:不再使用一个属性,而是将属性拆分成两个静态方法
        public static int GetGrade(DependencyObject obj)
        {
            return (int)obj.GetValue(GradeProperty);
        }
    
        public static void SetGrade(DependencyObject obj, int value)
        {
            obj.SetValue(GradeProperty, value);
        }
    
        //和依赖属性的不同点2:使用RegisterAttached进行注册,但是用法完全相同
        public static readonly DependencyProperty GradeProperty =
            DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(School), new PropertyMetadata(0));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public class Human:DependencyObject{}
    
    • 1

    增加一个button按钮,然后添加点击事件

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Human human = new Human();
        School.SetGrade(human, 6);
        int grade = School.GetGrade(human);
        MessageBox.Show(grade.ToString());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    附加属性的本质就是依赖属性,所以附加属性也可以使用Binding依赖在其他对象上。

    所对应的C#代码是

    TextBox txt = new TextBox();
    Grid.SetColumn(txt,1);
    Grid.setRow(txt,1);
    
    • 1
    • 2
    • 3

    案例:

    <Canvas>
        <Slider x:Name="sldX" Width="260" Minimum="50" Maximum="200" Canvas.Left="15" Canvas.Top="10"/>
        <Slider x:Name="sldY" Width="260" Minimum="50" Maximum="200" Canvas.Left="15" Canvas.Top="40"/>
        <Rectangle x:Name="Rect" Fill="Black" Width="30" Height="30" Canvas.Left="{Binding ElementName=sldX,Path=Value}" Canvas.Top="{Binding ElementName=sldY,Path=Value}"/>
    Canvas>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

  • 相关阅读:
    CSP-J2023入门组第二轮T4:旅游巴士
    Linux系统编程 102 alarm函数
    12大类150个图像处理和深度学习开源数据集
    redis缓存问题(数据库一致性,穿透,雪崩,击穿)
    设计模式15——享元模式
    力扣59-螺旋矩阵 II——边界判断
    【Helm三部曲】安装 chartmuseum 可视化界面 chartmuseumUi 【官方推荐安装方法】
    Vue3和Elment-Plus
    揭开ChatGPT面纱(2):OpenAI主类源码概览
    【Android进阶】9、用 RecyclerView 显示列表
  • 原文地址:https://blog.csdn.net/weixin_44064908/article/details/127691926