依賴附加屬性的定義
基本過程:聲明、注冊、包裝
依賴附加屬性必須在依賴對象,附加屬性不一定,關注的是被附加的對象是否是依賴對象
快捷方式: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"/>
使用: