WPF中的依赖属性

1.创建项目后下载两个NuGet程序包

2.创建一个MyButton类继承Button

MyButton类如下:

cs 复制代码
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.Media;

namespace WPF练习15依赖属性
{
    public class MyButton : Button
    {
        // 普通属性
        //public int CornerRadius { get; set; }

        // 依赖属性的包装器:其实就是一个普通属性
        // 依赖属性需要使用普通属性包装起来。
        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)GetValue(CornerRadiusProperty);
            }
            set
            {
                SetValue(CornerRadiusProperty, value);
            }
        }

        /*
        a、依赖属性所属的类必须继承至DependencyObject类,
        b、依赖属性的声明开头默认 public static readonly,
        c、依赖属性的命名以Property结尾,建议:包装器名称+Property
        d、使用DependencyProperty.Register静态方法注册。
        e、Register方法的三个参数(1、依赖属性包装器的名字,2、依赖属性保存值得类型,3、指明依赖属性的宿主类型)*/
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register(
                "CornerRadius",
                typeof(CornerRadius),
                typeof(MyButton),
                new PropertyMetadata(default(CornerRadius), CornerRadiusPropertyCallback));

        // 当CornerRadiusProperty依赖属性发生变化时,处理一些业务逻辑
        // d依赖对象,此依赖属性属于哪个控件?MyButton
        private static void CornerRadiusPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MyButton button = (MyButton)d;
            button.Content = e.NewValue.ToString();
        }


        // 普通属性
        private Brush myBackground;
        public Brush MyBackground
        {
            get { return myBackground; }
            set
            {
                myBackground = value;
                OnBackgroundChanged();
            }
        }
        // 普通事件
        public event EventHandler BackgroundChanged;
        private void OnBackgroundChanged()
        {
            BackgroundChanged?.Invoke(this, EventArgs.Empty);
        }

        // 路由事件:  公开静态只读的 public static readonly,这一点和依赖属性类似
        // 需要使用RoutedEvent来定义
        public static readonly RoutedEvent MyClickEvent = EventManager.RegisterRoutedEvent(
            "MyClick",
             RoutingStrategy.Bubble,  // 使用的路由策略:冒泡(从内层元素向外层元素执行)  直连(只执行本元素), 隧道(捕获,挖洞)
                                      // 路由事件使用的委托类型RoutedEventHandler public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
             typeof(RoutedEventHandler),
             typeof(MyButton));

        // 路由事件的包装器,用一个普通事件来包装一下路由事件。
        public event RoutedEventHandler MyClick
        {
            add { AddHandler(MyClickEvent, value); }  // 添加事件
            remove { RemoveHandler(MyClickEvent, value); }  // 移除事件
        }

        // 设置一下MyClick事件的执行时机,在点击的执行
        // 调用MyBackground1ChangedEvent
        protected override void OnClick()
        {
            // 路由事件的参数对象。是哪一个路由事件的参数呢?RoutedEvent = MyClickEvent
            RoutedEventArgs e = new RoutedEventArgs()
            {
                RoutedEvent = MyClickEvent,
            };
            this.RaiseEvent(e);  // 触发路由事件MyClickEvent
        }
    }
}

3.创建MainWindowViewModel

MainWindowViewModel代码如下:

cs 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace WPF练习15依赖属性.ViewModels
{
    public class MainWindowViewModel: ObservableObject
    {
        private CornerRadius cornerRadius = new CornerRadius(10);
        public CornerRadius CornerRadius
        {
            get { return cornerRadius; }
            set { SetProperty(ref cornerRadius, value); }
        }
    }
}

MainWindow.xaml.cs代码如下:

cs 复制代码
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 WPF练习15依赖属性
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void myButton_BackgroundChanged(object sender, EventArgs e)
        {
            MyButton myButton = (MyButton)sender;
            Console.WriteLine("修改了MyBackground属性");
            Console.WriteLine(myButton.MyBackground.ToString());
        }

        private void myButton_MyClick(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(e.RoutedEvent.Name);
        }
    }
}

结果如下:

相关推荐
Ialand~3 分钟前
深度解析 Rust 的数据结构:标准库与社区生态
开发语言·数据结构·rust
张人玉20 分钟前
WPF 静态样式与动态样式的定义及使用详解
ui·c#·wpf
在坚持一下我可没意见25 分钟前
Java 网络编程:TCP 与 UDP 的「通信江湖」(基于TCP回显服务器)
java·服务器·开发语言·笔记·tcp/ip·udp·java-ee
杜子不疼.39 分钟前
【Rust】异步处理器(Handler)实现:从 Future 本质到 axum 实战
android·开发语言·rust
学习编程之路40 分钟前
Rust内存对齐与缓存友好设计深度解析
开发语言·缓存·rust
无限进步_1 小时前
C语言字符串连接实现详解:掌握自定义strcat函数
c语言·开发语言·c++·后端·算法·visual studio
Han.miracle1 小时前
Java的多线程——多线程(二)
java·开发语言·线程·多线程
阿登林1 小时前
Unity3D与Three.js构建3D可视化模型技术对比分析
开发语言·javascript·3d
cherryc_1 小时前
JavaSE基础——第十二章 集合
java·开发语言
集成显卡2 小时前
Bun.js + Elysia 框架实现基于 SQLITE3 的简单 CURD 后端服务
开发语言·javascript·sqlite·bun.js