1、定义依赖属性
意义:支持WPF的特性功能:动画、数据绑定、样式。
2、步骤:
public string NewPassword
{
get { return (string)GetValue(NewPasswordProperty); }
set { SetValue(NewPasswordProperty, value); }
}
public static readonly DependencyProperty NewPasswordProperty =
DependencyProperty.Register("NewPassword", typeof(string), typeof(MainWindow), new PropertyMetadata(default(string)));
PropertyMetadata用来定义属性的元数据(默认数据)。
FrameworkPropertyMetadata继承于PropertyMetadata
属性变化通知回调
强制回调,强制转换值
表示用作验证依赖属性有效值的回调的方法
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set
{
SetValue(MyPropertyProperty, value);
}
}
static FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(
default(int),
new PropertyChangedCallback(OnPropertyChanged),
new CoerceValueCallback(OnCoreceValue));
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(
"MyProperty",
typeof(int),
typeof(MainWindow),
metadata,
new ValidateValueCallback(OnValidateValue));
private static bool OnValidateValue(object value)
{
if ((int)value > 1500)
return false;
return true;
}
private static object OnCoreceValue(DependencyObject d, object value)
{
var min = (d as MainWindow).Min;
var max = (d as MainWindow).Max;
if ((int)value < min)
return min;
if ((int)value > max)
return max;
return value;
}
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("值变化了[OnPropertyChanged]:" + e.NewValue);
}
1、Inherits标记
2、AddOwner方法
通过该种写法可以实现依赖属性值得共享。
public class Control1 : ContentControl
{
public int Prop
{
get { return (int)GetValue(PropProperty); }
set { SetValue(PropProperty, value); }
}
public static readonly DependencyProperty PropProperty =
DependencyProperty.Register("Prop", typeof(int), typeof(Control1),
new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));
}
public class Control2 : ContentControl
{
public int Prop
{
get { return (int)GetValue(PropProperty); }
set { SetValue(PropProperty, value); }
}
public static readonly DependencyProperty PropProperty =
Control1.PropProperty.AddOwner(typeof(Control2),
new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));
}
<local:Control1 Prop="123">
<local:Control2 x:Name="c2"/>
local:Control1>
<local:Control2 Prop="456">
<local:Control1 x:Name="c1"/>
local:Control2>
Control1和Control2的共享了属性Prop值。
1、使用场景
有一些属性不是依赖,没有可以绑定的功能
PasswordBox->Password
2、定义
DependencyProperty.RegisterAttached、Get包装方法、Set包装方法
public class PasswordAttached
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached(
"Password",
typeof(string),
typeof(PasswordAttached),
new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnPropertyChanged)));
public static string GetPassword(DependencyObject d)
{
return (string)d.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject d, string value)
{
d.SetValue(PasswordProperty, value);
}
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached(
"Attach",
typeof(bool),
typeof(PasswordAttached),
new FrameworkPropertyMetadata(default(bool), new PropertyChangedCallback(OnAttachChanged)));
public static bool GetAttach(DependencyObject d)
{
return (bool)d.GetValue(PasswordProperty);
}
public static void SetAttach(DependencyObject d, bool value)
{
d.SetValue(PasswordProperty, value);
}
static bool _isUpdating = false;
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox pb = d as PasswordBox;
if (pb == null || e.NewValue == null) return;
if (!_isUpdating)
{
pb.PasswordChanged -= Pb_PasswordChanged;
pb.Password = e.NewValue.ToString();
pb.PasswordChanged += Pb_PasswordChanged;
}
}
private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox pb = d as PasswordBox;
if (pb == null) return;
pb.PasswordChanged += Pb_PasswordChanged;
}
private static void Pb_PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox pb = sender as PasswordBox;
_isUpdating = true;
SetPassword(pb, pb.Password);
_isUpdating = false;
}
}
public partial class MainWindow : Window
{
public string NewPassword
{
get { return (string)GetValue(NewPasswordProperty); }
set { SetValue(NewPasswordProperty, value); }
}
public static readonly DependencyProperty NewPasswordProperty =
DependencyProperty.Register("NewPassword", typeof(string), typeof(MainWindow), new PropertyMetadata(default(string)));
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.NewPassword = "123";
}
}
<PasswordBox Height="30" Password=""
local:PasswordAttached.Attach="true"
local:PasswordAttached.Password="{Binding NewPassword,RelativeSource={RelativeSource AncestorType=Window,Mode=FindAncestor},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Button" Click="Button_Click" Height="40"/>
local:PasswordAttached.Password绑定了NewPassword,可实现属性值变化通知到界面,依赖属性的底层实现了通知功能。
通过类型转换器,可以在xaml中将字符串(例如:“1,5”)赋值为依赖属性Rangle对象。
public Range Range
{
get { return (Range)GetValue(RangeProperty); }
set { SetValue(RangeProperty, value); }
}
public static readonly DependencyProperty RangeProperty =
DependencyProperty.Register("Range", typeof(Range), typeof(MainWindow), new PropertyMetadata(default(Range)));
public class RangeTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string[] valueArray = value.ToString().Split(',');
if (valueArray.Length == 2)
return new Range(int.Parse(valueArray[0]), int.Parse(valueArray[1]));
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return (value as Range).ToString();
//return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(RangeTypeConverter))]
public class Range
{
public int MinValue { get; set; }
public int MaxValue { get; set; }
public Range() { }
public Range(int min, int max)
{
this.MinValue = min;
this.MaxValue = max;
}
public override string ToString()
{
return $"{MinValue},{MaxValue}";
}
}