WPF- 依赖属性、依赖附加属性以及类型转换
作者:@@神农
- 2022 年 3 月 15 日
本文字数:5023 字
阅读完需:约 16 分钟
一 、依赖属性
1、 依赖属性的意义与作用
数据绑定
复制代码
2、定义依赖属性
基本:声明 注册 包装
复制代码
//1 声明
public static DependencyProperty valueProperty;
//2 注册
static DependenProperties()
{
valueProperty = DependencyProperty.Register("value", typeof(string), typeof(DependenProperties),new PropertyMetadata(default(string)));
}
//3 包装
public string value
{
get
{
return (string)this.GetValue(valueProperty);
}
set
{
this.SetValue(valueProperty, "小明");
}
}
备注:在类中必须继承 DependencyObject
复制代码
3、依赖属性回调方法与参数
ValidateValueCallback :属性值验证回调
复制代码
//2 注册
static DependenProperties()
{
valueProperty = DependencyProperty.Register("value", typeof(string), typeof(DependenProperties),new PropertyMetadata(default(string),new PropertyChangedCallback (OnValueChangedCallback)),new ValidateValueCallback(OnValidateValueCallback));
}
//回调方法必须是静态方法
//参数一:DependencyObject : 属性所在的对象
//参数二:DependencyPropertyChangedEventArgs : 变化动作所关联的数据
public static void OnValueChangedCallback(DependencyObject o,DependencyPropertyChangedEventArgs arg)
{
......
}
//验证回调函数
//参数一:Object :属性将要写入的值【最新值】
//返回值:bool 类型:是否允许写入
public static bool OnValidateValueCallback(Object o)
{
......
return true;
}
复制代码
CoerceValueCallback:强制值回调
代码如下:
复制代码
//2 注册
static DependenProperties()
{
valueProperty = DependencyProperty.Register("value", typeof(string), typeof(DependenProperties),new PropertyMetadata(default(string),new PropertyChangedCallback (OnValueChangedCallback),new CoerceValueCallback() ),new ValidateValueCallback(OnValidateValueCallback));
}
//回调方法必须是静态方法
//参数一:DependencyObject : 属性所在的对象
//参数二:DependencyPropertyChangedEventArgs : 变化动作所关联的数据
public static void OnValueChangedCallback(DependencyObject o,DependencyPropertyChangedEventArgs arg)
{
......
}
//验证回调函数
//参数一:Object :属性将要写入的值【最新值】
//返回值:bool 类型:是否允许写入
public static bool OnValidateValueCallback(Object o)
{
......
return true;
}
//强制回调函数
// <param name="d">属性对象</param>
/// <param name="baseValue">当前属性的最新值</param>
/// <returns>希望属性可以接收的值</returns>
public static void OnCoerceValueCallback(DependencyObject d, object baseValue)
{
return null;
}
复制代码
PropertyChangedCallback:属性变化回调
代码如下:
复制代码
//2 注册
static DependenProperties()
{
valueProperty = DependencyProperty.Register("value", typeof(string), typeof(DependenProperties),new PropertyMetadata(default(string),new PropertyChangedCallback (OnValueChangedCallback) ));
}
//回调方法必须是静态方法
//参数一:DependencyObject : 属性所在的对象
//参数二:DependencyPropertyChangedEventArgs : 变化动作所关联的数据
public static void OnValueChangedCallback(DependencyObject o,DependencyPropertyChangedEventArgs arg)
{
......
}
复制代码
注意:
属性注册: 【推荐】
//属性注册
static CallBack()
{
ValueProperty = DependencyProperty.Register(
"Value",
typeof(string),
typeof(CallBack),
new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault| FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnValueChangesCallBack),new CoerceValueCallback (OnCoerceValueCallback)),
new ValidateValueCallback(ValidateValueCallback)
);
}
//FrameworkPropertyMetadata 对象比PropertyMetadata多了几个参数:
//其中的 FrameworkPropertyMetadataOptions. | FrameworkPropertyMetadataOptions. 选项参数,当值发生变化后他会重新渲染页面,重新显示最新值。
//FrameworkPropertyMetadataOptions选项:
//AffectsArrange、AffectsMeasure、AffectsParentArrange、AffectsParentMeasure:属性变化的时候,需要通知容器进行重新测量和排列。Margin值变化的时候,就会把相邻的对象挤开
//AffectsRender:属性值的变化导致元素重新渲染、重新绘制
//BindsTwoWayByDefault:默认情况以双向绑定的方式处理绑定行为
//Inherits:继承。FontSize,父对象进行这个属性设置的时候,会对子对象进行相同的影响
//IsAnimationProhibited:这个属性不能用于动画
//IsNotDataBindable:不能使用表达式,设置依赖属性
//Journal:Page开发,属性的值会被保存到 日志
//SubPropertiesDoNotAffectRender:对象属性子属性变化时,不去重新渲染对象
//DefaultValue:默认值
复制代码
输入属性值----->触发验证回调------>【验证通过】----->写入到属性值------>【值发生变化后】------>触发属性变化回调 -----> 强制回调。
4、依赖附加属性
1、依赖附加属性的意义与作用
给其他对象提供依赖属性。
比如有的属性不能绑定。【password】
2、 定义依赖属性 【新建 Controller 类:】
基本:
声明
public static DependencyProperty PasswordValueProperty;
复制代码
注册
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("PasswordValue", typeof(string), typeof(Controller),
new PropertyMetadata(default(string),
new PropertyChangedCallback(OnPropertyChangedCallback) )
);
复制代码
包装
public static string GetPasswordValue(DependencyObject obj)
{
return (string)obj.GetValue(MyPropertyProperty);
}
public static void SetPasswordValue(DependencyObject obj, string value)
{
obj.SetValue(MyPropertyProperty, value);
}
复制代码
值发生变化后触发的回调函数
public static void OnPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as PasswordBox).Password = (string)e.NewValue;
}
复制代码
xmal 代码如下:
<Window x:Class="WpfApp1.DependenProperties.DependenProperties"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1.DependenProperties"
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
Title="DependenProperties" Height="450" Width="800">
<Window.Resources>
<sys:String x:Key="pwd">123</sys:String>
</Window.Resources>
<Grid>
<PasswordBox Password="" local:Controller.PasswordValue="{Binding Source={StaticResource pwd}}"></PasswordBox>
</Grid>
</Window>
复制代码
3、主要回调
回调和依赖属性一样使用。
4、 属性元数据参数
同依赖属性一样。
5、 使用场景
6、与依赖属性的区别总结
依赖属性:必须在依赖对象里,附加属性不一定。
5、类型转换器
新建依赖属性类: 【Control】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1.TypeConverterDemo
{
[TypeConverter(typeof(TypeConvertDemo))]
public class Control
{
public double Width { get; set; }
public double Height { get; set; }
}
public class ControlProperty:ContentControl {
public Control Value
{
get { return (Control)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(Control), typeof(ControlProperty), new PropertyMetadata(null));
}
}
复制代码
新建数据类型转换类:【TypeConvertDemo】继承 TypeConverter
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp1.TypeConverterDemo
{
public class TypeConvertDemo : TypeConverter
{
/// <summary>
///类型转换
/// </summary>
/// <param name="context">上下文</param>
/// <param name="culture">当前本地化信息</param>
/// <param name="value">传递值</param>
/// <returns></returns>
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
var temp = Convert.ToString(value).Split(',');
var c = new Control()
{
Width = Convert.ToDouble(temp[0]),
Height = Convert.ToDouble(temp[1])
};
return c;
}
}
}
复制代码
新建 xaml:【Window1.xaml】
<Window x:Class="WpfApp1.TypeConverterDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1.TypeConverterDemo"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Grid>
<local:ControlProperty Value="12,34" x:Name="cc"></local:ControlProperty>
<Button Content="提交" Click="Button_Click"></Button>
</Grid>
</Window>
复制代码
Window1.xaml.cs Button 触发的事件
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.Shapes;
namespace WpfApp1.TypeConverterDemo
{
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_ = this.cc.Value;
}
}
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 2
版权声明: 本文为 InfoQ 作者【@@神农】的原创文章。
原文链接:【http://xie.infoq.cn/article/b84b2f5197005028aa6f021d3】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
@@神农
关注
还未添加个人签名 2022.03.14 加入
好好学习,天天向上!
评论