WPF依赖附加属性

news/2024/7/24 9:31:54 标签: wpf, c#

依赖附加属性的定义

基本过程:声明、注册、包装

依赖附加属性必须在依赖对象,附加属性不一定,关注的是被附加的对象是否是依赖对象

快捷方式:propa + tab

关键字:RegisterAttached

// 方法封装
public static int GetIndex(DependencyObject obj)
{
    return (int)obj.GetValue(IndexProperty);
}

public static void SetIndex(DependencyObject obj, int value)
{
    obj.SetValue(IndexProperty, value);
}

// 声明与注册
public static readonly DependencyProperty IndexProperty =
    DependencyProperty.RegisterAttached("Index", typeof(int), typeof(XHPanel), new PropertyMetadata(-1));

依赖附加属性的意义和作用

1. 用来辅助布局(布局控件与子控件的关系)

一般容器控件提供给子控件使用的,如果Grid.Row

使用方式:在容器控件中检查每个子项,从子项中获取附加属性的值 容器对象调用对应的GetValue方法,传入给被附加对象

a. 自定义控件的附加属性

父亲的属性:

// 方法封装
public static int GetIndex(DependencyObject obj)
{
    return (int)obj.GetValue(IndexProperty);
}

public static void SetIndex(DependencyObject obj, int value)
{
    obj.SetValue(IndexProperty, value);
}

// 声明与注册
public static readonly DependencyProperty IndexProperty =
    DependencyProperty.RegisterAttached("Index", typeof(int), typeof(XHPanel), new PropertyMetadata(-1));

使用方法:

可以在子控件中都使用Index属性

<local:XHPanel Test="12" ColumnSpace="20" RowSpace="20" Visibility="Collapsed">
  <Border Height="100" Background="Red" local:XHPanel.Index="1" />
  <Border Height="100" Background="Orange" local:XHPanel.Index="2" />
  <Border Height="100" Background="Yellow" local:XHPanel.Index="3"/>
  <Border Height="100" Background="Green" local:XHPanel.Index="4"/>
  <Border Height="100" Background="LightGreen" local:XHPanel.Index="5"/>
  <Border Height="100" Background="Blue" local:XHPanel.Index="6"/>
  <local:DependencyPropertyStudy local:XHPanel.Index="7" x:Name="dps" Background="Purple" Height="100"/>
</local:XHPanel>

在执行布局的时候,可以获取每个子控件的Index,进行不一样的布局:

获取部分的核心代码:

protected override Size ArrangeOverride(Size finalSize)
{
    for (int i = 1; i < newElements.Count+1; i++)
    {
        var index = GetIndex(item); // 获取对应对象的Index 附加属性值
    }
    // 根据index的不一样,进行不一样的布局
    .....
    return base.ArrangeOverride(finalSize);
}
2. 用来扩展绑定属性(单独应对对象功能)

一般对接特定对象,比如PasswordBox

使用方法:定义一个类,在类定义相关附加属性,利用这些附加属性进行数据与控件属性的转接

需求:PasswordBox中的password属性不可以绑定,不是依赖属性,但是我这边又需要动态赋值,所以,此时需要写个扩展属性:

核心代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace XH.PropertyLesson
{
    public class PWHelper
    {
        public static string GetPassword(DependencyObject obj)
        {
            return (string)obj.GetValue(PasswordProperty);
        }

        /// <summary>
        /// 设置Password
        /// </summary>
        /// <param name="obj">所附加的对象</param>
        /// <param name="value"></param>
        public static void SetPassword(DependencyObject obj, string value)
        {
            obj.SetValue(PasswordProperty, value);
        }

        // Using a DependencyProperty as the backing store for Password.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.RegisterAttached(
                "Password", 
                typeof(string), 
                typeof(PWHelper), 
                new PropertyMetadata(
                    "",
                    new PropertyChangedCallback(OnPasswordChanged)));

        // 1、可以获取到对应的控件 PasswordBox
        // 2、关联两个方向
        //    - 从绑定到控件
        //    - 从控件到绑定(针对拿到的控件进行PasswordChanged事件的绑定)

        /// <summary>
        /// Password修改回调函数
        /// </summary>
        /// <param name="DependencyObject">实际附加的对象</param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (d as PasswordBox);
            if (control == null) return;

            control.Password = e.NewValue as string;
        }

        private static void Control_PasswordChanged(object sender, RoutedEventArgs e)
        {
            SetPassword((DependencyObject)sender, (sender as PasswordBox).Password);
        }

        public static object GetAttached(DependencyObject obj)
        {
            return (object)obj.GetValue(AttachedProperty);
        }

        public static void SetAttached(DependencyObject obj, object value)
        {
            obj.SetValue(AttachedProperty, value);
        }

        // 挂载事件
        public static readonly DependencyProperty AttachedProperty =
            DependencyProperty.RegisterAttached("Attached", typeof(object), typeof(PWHelper), 
                new PropertyMetadata(null,new PropertyChangedCallback(OnAttachedChanged)));

        private static void OnAttachedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (d as PasswordBox);
            if (control == null) return;

            // 防止多次附加事件 可以先减 后加
            control.PasswordChanged -= Control_PasswordChanged; 
            control.PasswordChanged += Control_PasswordChanged; 
        }
    }
}

xaml使用代码:

<PasswordBox PasswordChar="*" Height="30" Width="100" 
  local:PWHelper.Password="{Binding }"
  local:PWHelper.Attached="1"/>

使用:


http://www.niftyadmin.cn/n/5546971.html

相关文章

【十万个为什么】为什么步进电机使用的电压比规格书额定电压高

步进电机具有额定相电压和额定相电流。例如&#xff0c;一个典型的步进电机可能具有4V的额定电压和最大电流为2.2A。基本上&#xff0c;这意味着如果您将其连接到4V电压&#xff0c;它将会吸引2.2A的电流&#xff08;电压除以电阻&#xff09;。如果您尝试以更高的电压运行它&a…

概率论习题

泊松分布习题 假设你在医院值班&#xff0c;每天需要安保人员出动的次数N~P(1),则关于任一天安保人员出动次数&#xff1a; A&#xff1a;出动一次的概率是多少 B&#xff1a;出动次数小于等于一次的概率为 C&#xff1a;出动次数小于一次的概率为 D&#xff1a;若随机事件发生…

怎样卸载电脑上自带的游戏?

卸载电脑上自带的游戏通常是一个简单的过程&#xff0c;以下是几种常见的方法&#xff0c;您可以根据自己的操作系统版本选择相应的步骤进行操作&#xff1a; 方法一&#xff1a;通过“设置”应用卸载&#xff08;适用于Windows 10和Windows 11&#xff09; 1. 点击开始菜单&…

Java8 - Stream API 处理集合数据

Java 8的Stream API提供了一种功能强大的方式来处理集合数据&#xff0c;以函数式和声明式的方式进行操作。Stream API允许您对元素集合执行操作&#xff0c;如过滤、映射和归约&#xff0c;以简洁高效的方式进行处理。 下面是Java 8 Stream API的一些关键特性和概念&#xff…

Spring Boot项目中JPA操作视图会改变原表吗?

一直有一种认识就是:使用JPA对视图操作,不会影响到原表。 直观的原因就是视图是一种数据库中的虚拟表,它由一个或多个表中的数据通过SQL查询组成。视图不包含数据本身,而是保存了一条SQL查询,这条查询是用来展示数据的。 但是在实际项目种的一个场景颠覆和纠正了这个认识…

Mini-L-CTF-2022 minispringboot Thymeleaf模板注入 spel的绕过

Mini-L-CTF-2022 minispringboot Thymeleaf模板注入 spel的绕过 就是一个低版本的Thymeleaf注入 漏洞点 public class MainController {GetMapping({"/{language}"})public String test(PathVariable(name "language") String language, RequestParam(…

0703_ARM7

练习&#xff1a; 封装exti&#xff0c;cic初始化函数 //EXTI初始化 void hal_key_exti_init(int id,int exticr,int mode){//获取偏移地址int address_offset (id%4)*8;//获取寄存器编号int re_ser (id/4)1;//printf("address_offset%d,re_ser%d\n",address_o…

【竞技宝】欧洲杯:西班牙进四强,队长做出让球迷意外的重要决定

西班牙是本届欧洲杯最具冠军相的球队,因为球队从小组赛开始就表现强势。西班牙进攻中能多点开花,防守端则是滴水不漏,让很多球迷和媒体都眼前一亮。另外,西班牙队打法非常好看,不管是小组赛还是淘汰赛从来不苟着踢。所以,西班牙就吸引了一批新球迷关注和青睐,认为斗牛士军团只要…