依赖附加属性的定义
可使用代码片段-propa快速生成,输入propa后按两次Tab键
public static int GetMyProperty(DependencyObject obj)
{
return (int)obj.GetValue(MyPropertyProperty);
}
public static void SetMyProperty(DependencyObject obj, int value)
{
obj.SetValue(MyPropertyProperty, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
属性名称MyProperty,方法名默认为GetMyProperty和SetMyProperty不要随意更改。
DependencyProperty.RegisterAttached的参数与依赖属性一致。
依赖属性所在的类必须继承DependencyObject,而依赖附加属性所在的类不需要。
依赖属性必须在依赖对象,而依赖附加属性不一定,关注的是被附加的对象是否是依赖对象。
在普通类中定义依赖属性,GetValue与SetValue报错,因为这两个方法定义在DependencyObject中。
在普通类中可以定义依赖附加属性。
依赖附加属性的意义与作用
给其他对象提供依赖属性功能
public class ZxPanel : Panel
{
// 依赖附加属性的方法封装
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(ZxPanel), new PropertyMetadata(-1));
}
在ZxPanel类中定义一个依赖附加属性Index。
<Border Background="Orange" Height="50" local:ZxPanel.Index="3"/>
在Xaml中为Border添加依赖附加属性。
有些对象中不能做绑定的功能
PasswordBox控件的Password属性不具备绑定功能。
public class PWHelper
{
public static string GetPassword(DependencyObject obj)
{
return (string)obj.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject obj, string value)
{
obj.SetValue(PasswordProperty, value);
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PWHelper), new PropertyMetadata(""
, new PropertyChangedCallback(OnPasswordChanged)));
/// <summary>
///
/// </summary>
/// <param name="dependencyObject">实附加的对象</param>
/// <param name="e"></param>
private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//var control = (d as PasswordBox);
//if (control == null) return;
if (d is PasswordBox control)
{
control.Password = e.NewValue.ToString();
}
}
}
在PWHelper类中定义一个依赖附加属性Password,并添加值变化回调,将新值赋值给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;
}
private static void Control_PasswordChanged(object sender, RoutedEventArgs e)
{
SetPassword((DependencyObject)sender, (sender as PasswordBox).Password);
}
再定义一个依赖附加属性Attached,并添加值回调,用来挂载事件。
依赖附加属性可以使用绑定。
布局控件做动态子项
public class ZxPanel : Panel
{
// 依赖附加属性的方法封装
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(ZxPanel), new PropertyMetadata(-1));
}
在继承Panel类的ZxPanel类中定义依赖附加属性Index。
<local:ZxPanel ColumnSpace="10" RowSpace="10" Test="123">
<Border Background="Orange" Height="50" local:ZxPanel.Index="3"/>
<Border Background="Green" Height="50"/>
<Border Background="Blue" Height="50"/>
<Border Background="Red" Height="50"/>
<local:DependencyPropertyStudy local:ZxPanel.Index="2" Height="50" Background="Gray"
x:Name="dps"/>
</local:ZxPanel>
在ZxPanel控件下的子项可以使用local:ZxPanel.Index="3"。
protected override Size MeasureOverride(Size availableSize)
{
double total_y = 0;
double per_width = (availableSize.Width - ColumnSpace * 2) / 3;
foreach (UIElement item in this.InternalChildren)
{
item.Measure(new Size(per_width, double.MaxValue));
total_y += item.DesiredSize.Height + RowSpace;
}
return new Size(availableSize.Width, total_y);
}
// 排列
protected override Size ArrangeOverride(Size finalSize)
{
double offset_y = 0, offset_x = 0;
double per_width = (finalSize.Width - ColumnSpace * 2) / 3;
double maxHeight = 0;
List<FrameworkElement> elements = new List<FrameworkElement>();
for (int i = 0; i < this.InternalChildren.Count; i++)
{
elements.Add((FrameworkElement)this.InternalChildren[i]);
}
for (int i = 1; i < this.InternalChildren.Count + 1; i++)
{
UIElement item = elements.FirstOrDefault(e => GetIndex(e) == i);
if (item == null)
{
// 这个是容器中的子控件(DependencyPropertyStudy)
item = this.InternalChildren[i - 1];
}
//var index = GetIndex(item);// 获取对应对象的Index附加属性值
item.Arrange(new Rect(offset_x, offset_y, per_width, item.DesiredSize.Height));
maxHeight = Math.Max(maxHeight, item.DesiredSize.Height);
if (i % 3 == 0)
{
offset_y += maxHeight + RowSpace;
offset_x = 0;
maxHeight = 0;
}
else
offset_x += per_width + ColumnSpace;
}
return base.ArrangeOverride(finalSize);
}
在ZxPanel类中重写MeasureOverride与ArrangeOverride方法,重新定义控件的测量与排序方法。安装子控件的Index属性重新进行排序。
此用法与<Grid的属性<Grid.Column>和<Grid.Row>类似。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<local:DependencyPropertyStudy Tag="123" Command="{Binding}" CP="{Binding}"
DPS="{Binding Value}" Grid.Column="1"/>
</Grid>
Grid.Column="1"用于辅助布局控件
标签:obj,int,附加,static,DependencyObject,WPF,public,属性 From: https://www.cnblogs.com/ZHIZRL/p/17848436.html