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 加入
好好学习,天天向上!











评论