专栏首页dino.c的专栏[UWP]依赖属性1:概述

[UWP]依赖属性1:概述

1. 概述

依赖属性(DependencyProperty)是UWP的核心概念,它是有DependencyObject提供的一种特殊的属性。由于UWP的几乎所有UI元素都是集成于DependencyObject的FramewordElement,并且这些UI元素的几乎所有属性及它们出现在XAML中的几乎所有属性都是依赖属性,所以可以说依赖属性是专门为UI设计的属性系统。

依赖属性的定义:

/// <summary>
/// 获取或设置Title的值
/// </summary>  
public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}

/// <summary>
/// 标识 Title 依赖属性。
/// </summary>
public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register("Title", typeof(string), typeof(MyPage), new PropertyMetadata(string.Empty));

如上述代码所示,和CLR属性不同依赖属性需要定义TitleProperty ,然后在属性包装器(Getter和Setter)中通过GetValue和SetValue函数操作属性值。

2. 使用的场景

UWP的依赖属性经过大幅简化(相对于WPF),更关注它的核心功能:使用绑定,通过多个输入计算属性值,属性值变化通知,节约内存使用。

2.1 绑定

通过属性包装器,依赖属性可以像CLR属性那样使用,也可以在XAML中通过绑定来使用,这是CLR属性不能提供的功能。

在XAML中使用:

<TextBlock x:Name="TextElement"
            Text="{Binding Title}" />

在代码中使用:

var binding = new Windows.UI.Xaml.Data.Binding();
binding.Path = new PropertyPath("Title");
TextElement.SetBinding(TextBlock.TextProperty, binding);

2.2 通过多个输入计算属性值

在UWP中依赖属性通过多个输入源计算属性的值,从而使开发人员就避免了不必要的属性设置值或者处理属性值变更通知。以下列表从优先级由高到低列出了依赖属性的使用顺序。

  • 动画值 正在运行的动画,或具有 HoldEnd 行为的动画。若要进行动画处理,动画的目标属性必须是依赖项属性。
  • 本地值 在代码中直接为对象实例设置的属性值,或者在 XAML 中设置的属性值。 本地值可以通过调用ClearValue函数清除,从而使属性值还原成默认值(以我的经验来说,很少会用到)。
  • 模板属性 如果在某个模板(来自 ControlTemplate 或 DataTemplate)中创建一个元素,该元素就会拥有这些模板属性。
  • 样式设置器 Style中的Setter。
  • 继承值 元素可以从其在对象树中的父级继承依赖项属性的值。譬如开发人员不必为每个TextBlock设置FontSize,只需要为父容器设置FontSize即可套用到父容器中的所有TextBlock上。
  • 默认值 不是指数据类型的默认值,是指PropertyMetadata中指定的默认值。在上面Title的例子中,默认值是string.Empty。

2.3 属性值变化通知

使用依赖属性,不必再实现INotifyPropertyChanged即可在属性改变时通知UI更新。也可以在PropertyMeta中使用PropertyChangedCallback或DependencyObject.RegisterPropertyChangedCallback监视依赖属性的属性值改变。

2.4 节约内存使用

前面提到,UWP可以不必为所有值都设置值,UI元素的依赖属性可以从样式、继承值、默认值等计算出实际值,并不需要分配内存;如果设置了本地值,这个本地值将存储在HashTable中,之后从这个HashTable中读取。这是一种以时间换空间的做法。 假设一个Control自身及所继承的FrameworkElement等父类型中所有的属性加起来大概50个,它的控件模板中大概有3个FrameworkElement,所有属性都是double类型并且所有都不必要设置值,一个Control就可以节省50 * 3 * 8=1200字节的内存空间。我做过的系统最多同时在UI上放了10W个Control,那么就总共节省了大概100M内存。 这么极端的情况也才节省这点内存,作用好像也没那么大(难道我算错了?)。关于节约内存这点稍微了解下就好,有助于了解依赖属性的原理,并且面试的时候有可能有帮助。

3 依赖属性和CLR属性之间的选择

使用依赖属性的情况

  • 基本上所有继承DependencyObject的类中的属性都应该是依赖属性;
  • 需要使用Binding、Style或动画设置值的属性;
  • 需要监视属性值变化通知;
  • 内存真的真的不够用;

使用CLR属性的情况

  • 集合属性。在UWP中常见的集合属性,只有ItemsControl的ItemsSource等少数几个是依赖属性,其它大部分都是CLR属性,譬如Hub的Sections;
  • CPU性能敏感的场合。依赖属性是用时间换空间的概念,假如需要频繁读写而又不需要绑定,可以考虑使用CLR属性;

4. 依赖属性和线程

所有依赖属性都只能在UI线程上使用,否则会抛异常(“应用程序调用一个已为另一线程整理的接口。”)。不过如果使用Async模式的话通常会回避了线程的问题。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [WPF自定义控件]从ContentControl开始入门自定义控件

    我去年写过一个在UWP自定义控件的系列博客,大部分的经验都可以用在WPF中(只有一点小区别)。这篇文章的目的是快速入门自定义控件的开发,所以尽量精简了篇幅,更深...

    dino.c
  • [UWP 自定义控件]了解模板化控件(2):模仿ContentControl

    ContentControl是最简单的TemplatedControl,而且它在UWP出场频率很高。ContentControl和Panel是VisualTre...

    dino.c
  • [UWP]依赖属性2:使用依赖属性

    以上代码为一个相对完成的依赖属性例子(还有一些功能比较少用就不写出了),从这段代码可以看出,自定义依赖属性的步骤如下:

    dino.c
  • 达观数据前端分享:理解 JavaScript 中的对象的属性

    在达观数据的前端工作中,对象的属性是经常接触和使用的,正好最近重温了一下《JavaScript 高级程序设计》,把书中理解对象属性的部分整理一下与大家分享。 ...

    达观数据
  • 《OEA - 实体扩展属性系统 - 设计方案说明书》

        这篇设计文档是 12 月份写来参加公司的研发峰会的,自己倒是信心满满,不过最后还是没有入围。现在想想也没啥大用,所以贴出来,期待与园友交流。     文...

    用户1172223
  • 18.Swift学习之属性与方法

    YungFan
  • 前端基础-CSS属性选择器

    cwl_java
  • 【Rust每周一知】 Attribute 属性

    Rust 中的属性数量非常多。而且具有可扩展性(可自定义属性)。Rust 的属性语法遵从 C# 定义并标准化了的属性规范ECMA-334。

    MikeLoveRust
  • Workbook工作簿对象属性

    Activeworkbook.name表示当前活动工作簿的name属性,即当前excel文件的名称为vba.xlsm。

    无言之月

扫码关注云+社区

领取腾讯云代金券