打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
依赖属性、依赖附加属性以及类型转换

一 、依赖属性

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;
        }
    }
}

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
[WPF]实现密码框的密码绑定
WPF整理-为控件添加自定义附加属性
WPF基础到企业应用系列7——深入剖析依赖属性(WPF/Silverlight核心)
建立Silverlight自定义控件(4)--添加自定义属性
How to Add Properties to Custom WPF Control
WPF学习笔记三 依赖属性
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服