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);
        }
    }
}

结果如下:

相关推荐
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法
echoarts2 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Aomnitrix2 天前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
每天回答3个问题2 天前
UE5C++编译遇到MSB3073
开发语言·c++·ue5
伍哥的传说2 天前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
小莞尔2 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
我是菜鸟0713号2 天前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_2 天前
QT(4)
开发语言·汇编·c++·qt·算法
Brookty2 天前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
百锦再2 天前
[特殊字符] Python在CentOS系统执行深度指南
开发语言·python·plotly·django·centos·virtualenv·pygame