依赖附加属性的定义
基本过程:声明、注册、包装
依赖附加属性必须在依赖对象,附加属性不一定,关注的是被附加的对象是否是依赖对象
快捷方式: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"/>
使用: