加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

WPF依赖属性

发布时间:2020-12-14 05:29:02 所属栏目:百科 来源:网络整理
导读:理解依赖属性 依赖属性支持的特征包括:动画、数据绑定、样式。 可以分配WPF元素的属性大部分都是依赖属性。 依赖属性和常规属性的用法相同。 WPF设计了依赖属性支持其特有的动态特性,并且不干扰其他系统的.net代码。 定义依赖属性 public class FrameworkE

理解依赖属性

依赖属性支持的特征包括:动画、数据绑定、样式。

可以分配WPF元素的属性大部分都是依赖属性。

依赖属性和常规属性的用法相同。

WPF设计了依赖属性支持其特有的动态特性,并且不干扰其他系统的.net代码。

定义依赖属性

public class FrameworkElement: UIElement,...
{
    public static readonly DependencyProperty MarginProperty;
    ...
}

依赖属性的定义是静态属性。这是为了使其一直可用。在类内的实例之间、甚至在不同的类之间如WPF元素共享。

根据命名约定,依赖属性定义时名字带有Property后缀。使用依赖属性可以省略Property后缀。

依赖属性是只读的,只能在类的静态构造函数中设置,见下节。

注册依赖属性

依赖属性不能被直接实例化,在创造后不能被修改,也就是其不可变的。所以,依赖属性类没有公有的构造函数,并且定义为readonly。其构造必须在类的静态函数中,通过静态的DependencyProperty.Register()方法设置。

static FrameworkElement()
{
    var metadata = new FrameworkPropertyMetadata(
      new Thickness(),FrameworkPropertyMetadataOptions.AffectsMeasure);

    MarginProperty = DependencyProperty.Register("Margin",typeof(Thickness),typeof(FrameworkElement),metadata,new ValidateValueCallback(FrameworkElement.IsMarginValid));
    ...
}

FrameworkPropertyMetadata类用于设置依赖属性支持什么功能。

Register()方法的参数分别为:属性名称、属性类型、所属类的类型、额外的属性设置(可选)、执行验证的回调(可选)。

两个可选属性值得研究。FrameworkPropertyMetadata的详细描述见95页。

包裹依赖属性

调用定义在DependencyObject中的SetValue()和GetValue()方法包裹属性。

public Thickness Margin
{
    set { SetValue(MarginProperty,value); }
    get { return (Thickness)GetValue(MarginProperty); }
}

仅此而已,不应该再添加额外的代码如验证输入值、引发事件等等。

验证输入值应使用DependencyProperty.ValidateValueCallback。

引发事件应使用FrameworkPropertyMetadata.PropertyChangedCallback 。

现在可以使用属性了:

myElement.Margin = new Thickness(5);

晚些时候,可能希望移除局部值设置,仿佛你从未设置它。

myElement.ClearValue(FrameworkElement.MarginProperty);

使用依赖属性

依赖属性支持两个关键的特征:改变通知和动态值求解。

如果希望反应属性改变,有二个选择:属性值绑定、或触发器。

动态值求解,依赖属性根据下列因素求基础值(后来者赢):

  1. 默认值
  2. 继承的值
  3. 样式
  4. 本地值(直接设置的值)

WPF通过4个步骤求得属性值:

  1. 基础值
  2. 如果属性通过表达式设置值,计算表达式。WPF支持两种表达式:数据绑定和资源。
  3. 应用动画
  4. 通过CoerceValueCallback修正值

共享依赖属性

即使类的层次架构互相独立,一些类共享同样的依赖属性。比如,TextBlock.FontFamily和Control.FontFamily都指向相同的依赖属性TextElement.FontFamilyProperty。TextBlock和Control类知识简单的重用它,依靠的是DependencyProperty.AddOwner()方法:

TextBlock.FontFamilyProperty =
  TextElement.FontFamilyProperty.AddOwner(typeof(TextBlock));

自定义类的时候可以使用这个技术。

重用依赖属性会导致一些奇怪的副作用。使用样式时常会出现,比如,你使用样式设置TextBlock.FontFamily属性,Control.FontFamily属性也会被影响。

附加属性

相比普通的依赖属性,注册一个附加属性使用RegisterAttached()方法代替Register()方法。如:

var metadata = new FrameworkPropertyMetadata(
  0,new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged));
Grid.RowProperty = DependencyProperty.RegisterAttached("Row",typeof(int),typeof(Grid),new ValidateValueCallback(Grid.IsIntValueNotNegative));

当定义附加属性时,不需要.net属性包裹器。它需要一对静态方法,用来设置或获取属性值。如:

public static int GetRow(UIElement element)
{
    if (element == null)
    {
        throw new ArgumentNullException(...);
    }
    return (int)element.GetValue(Grid.RowProperty);
}
public static void SetRow(UIElement element,int value)
{
    if (element == null)
    {
        throw new ArgumentNullException(...);
    }
    element.SetValue(Grid.RowProperty,value);
}

用法:

Grid.SetRow(txtElement,0);

另一个用法:

txtElement.SetValue(Grid.RowProperty,0);

属性验证

WPF提供两条路阻止无效值:ValidateValueCallback、CoerceValueCallback。

当设置一个依赖属性时,依次经过:CoerceValueCallback、ValidateValueCallback、PropertyChangedCallback

Validation回调

相当于正常属性的set部分中的验证。

其签名为接受一个object输入参数,返回boolean值。返回值为真表示接受,为假表示拒绝。

private static bool IsMarginValid(object value)
{
    Thickness thickness1 = (Thickness) value;
    return thickness1.IsValid(true,false,true,false);
}

有一个限制,它是一个静态方法,不能访问正被验证的对象,不能使用对象中的其他属性。

Coercion回调

用于验证互相关联的属性

private static object CoerceMaximum(DependencyObject d,object value)
{
    RangeBase base1 = (RangeBase)d;
    if (((double) value) < base1.Minimum)
    {
        return base1.Minimum;
    }
    return value;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读