WPF 学习笔记

XAML

XAML 文档

  • 在运行期被编译成 BAML。
  • 元素对应于 .NET 类。
  • 一个元素可以嵌在另一个元素中。
  • 可以使用属性。

XAML 名字空间

依赖属性(Dependency Property)

相比较于普通属性,依赖属性有以下特点:

  • 变化通知(change notification)
  • 节省内存
  • 使用某种带优先级决定策略(resolution strategy)来读取属性的值。
    属性值可以依赖于其他对象,适用于数据绑定,属性值继承等场景。

依赖属性的声明

  • 宿主必须是 DependencyObject 的子类。
  • 使用 DependencyProperty 类型声明依赖属性。(public static readonly)
  • 使用 DependencyProperty.Register 方法注册依赖属性。
  • 使用属性包装器包装依赖属性(调用 GetValue, SetValue)。

附加属性(Attached Property)

附加属性是所处环境(上级元素)所附加的属性,是一种特殊的依赖属性。

  • 宿主必须是 DependencyObject 的子类。
  • 使用 DependencyProperty 类型声明附加属性。(public static readonly)
  • 使用 DependencyProperty.RegisterAttached 方法注册附加属性。
  • 使用静态方法 GetXXX, SetXXX 存取附加属性(调用 GetValue, SetValue)。

路由事件(Routed Events)

路由事件被用来实现事件的路由功能。

路由事件的声明

  • 宿主必须是 FrameworkElement 的子类。
  • 使用 RoutedEvent 类型声明路由事件。(public static readonly)
  • 使用 EventManager.RegisterRoutedEvent 方法注册路由事件。
  • 使用标准 .NET 事件声明机制包装路由事件(add, remove)。

路由策略

  • 直接:事件由事件源直接触发。
  • 冒泡:由事件源逐级向上传递直至根元素。
  • 隧道:由根元素逐级向下传递直至事件源。
    隧道事件名通常以 Preview 打头。

附加事件(Attached Event)

由下级元素的冒泡事件附加的事件。

布局(Layout)

不应该用硬编码来指定控件的尺寸和位置。

常用面板容器

  • StackPanel
    纵向或横向布局,只有一列或一行
  • WrapPanel
    纵向或横向布局,可以不止一列或一行,空间不够时可换列或换行
  • DockPanel
    东西南北中的布局模式
  • Grid
    将指定区域划分为若干行和列
  • Canvas
    使用绝对位置来定位控件

布局属性

  • HorizontalAlignment:Center, Left, Right, or Stretch
    水平方向可以选择居中,左对齐,右对齐或延伸。
  • VerticalAlignment:Center, Top, Bottom, or Stretch
    垂直方向可以选择居中,左对齐,右对齐或延伸。
  • Margin:外边距,可以选择一个数字或四个数字(左上右下)
  • MinWidth MinHeight:
  • MaxWidth MaxHeight:
  • Width Height:

Border(边框)

  • Background:背景色
  • BorderBrush BorderThickness:
  • CornerRadius:
  • Padding:内边距

资源(Resources)

使用资源标签将有用的对象聚合于一处,便于修改和复用。即使用资源是为了在应用程序的不同部分共享某些对象。
在 XAML 中定义资源相当于在程序代码中定义常量。

  • 资源在资源(Resources)标签中定义。使用字符串作为键值(x:Key=)。
  • 通常在顶层的 Window (级别)标签中定义。

静态资源和动态资源

  • 静态资源只提取一次(预先提取)
  • 动态资源可提取多次(只在需要时提取),资源对象在代码中被替换时也能及时响应
  • 通常不需要动态资源

资源的使用

  • 非共享资源(Nonshared Resources):使用 x:Shared="False" 创建独立的资源对象,通常不需要
  • 在代码中可以调用 FindResource 方法定位资源
  • 应用程序级别的资源:
  • 系统资源(System Resources):

资源字典(Resource Dictionary)

在不同的工程中共享资源需要使用资源字典,资源字典通常用于定义应用程序的皮肤(Skin)。

  • 使用单独的文件定义资源字典
  • 在资源标签下使用 ResourceDictionary 标签将资源字典并入程序中
  • 额外的资源此时只能在 ResourceDictionary 标签下定义

样式(Style)

样式是一组(属性及事件)设置的集合。样式在资源中定义。
样式的构成

  • Setters:
    • Setter:属性设置
    • EventSetter:事件设置
  • Triggers:条件满足时自动触发对某些设置,条件不满足时自动还原
    • Trigger:观察控件的某个依赖属性,属性值为某个特定值时触发
    • MultiTrigger:多个 Trigger 同时满足时触发
    • DataTrigger:观察控件所绑定的数据对象的某个属性,属性值为某个特定值时触发
    • MultiDataTrigger:多个 DataTrigger 同时满足时触发
    • EventTrigger:控件的某个特定事件发生时触发
  • Resources:局部于样式的资源
  • BasedOn:样式基于某个类型
  • TargetType:目标类型,用于自动应用样式

数据绑定(Data Binding)

通过在目标对象的目标属性中设定绑定源及其值路径(属性名 Path=)来实现数据绑定。

绑定其他界面元素

  • 指定界面元素名作为绑定源。(ElementName=)
  • 绑定模式(方向 Mode=)
    • OneWay:单向,源属性到目标属性
    • TwoWay:双向,源属性到目标属性,目标属性到源属性
    • OneTime:单向,源属性到目标属性,仅限一次
    • OneWayToSource:单向,目标属性到源属性
    • Default:由目标对象元数据决定
  • 方向为目标属性到源属性时触发源属性更新的因素(UpdateSourceTrigger=)
    • PropertyChanged:目标属性变更时
    • LostFocus:目标属性变更后且失去焦点时
    • Explicit:明确调用 UpdateSource 方法时
    • Default:由源属性元数据决定

绑定数据源

指定资源或对象作为绑定源。(Source=)

绑定相对数据源

寻找某个与自身存在某种相对位置关系的元素,把它作为绑定源。(RelativeSource=)

  • 绑定模式(目标 Mode=)
    • Self:自身
    • FindAncestor:上级元素
    • PreviousData
    • TemplatedParent
  • 绑定模式为上级元素时需要满足的条件
    • 指定上级元素的种类(AncestorType=)
    • 找到第n个指定种类的上级元素(AncestorLevel=)

绑定数据上下文

没有指定数据源时,逐级向上寻找上级元素的 DataContext 属性,该属性非空时把它作为绑定源。

绑定对象的集合

使用 ObservableCollection

数据转换(Data Conversion)

  • 字符串格式化(StringFormat=)
  • 创建值转换器(Value Converters)
    • 实现 IValueConverter 接口
    • 在 Convert 方法中将源对象转换为目标对象
    • 在 ConvertBack 方法中将目标对象转换为源对象
  • 使用值转换器
    • 引入值转换器所在的名字空间
    • 在资源中创建值转换器的实例
    • 绑定值转换器的实例(Converter=)

多重绑定

使用 MultiBinding 标签绑定多个源。
在多重绑定标签里也可以使用

  • 字符串格式化
  • 值转换器(实现 IMultiValueConverter 接口)

命令(Command)

命令是程序所执行的某些功能(任务)抽象后的产物。
通过命令可以

  • 将执行这些任务时的业务逻辑集中于一处
  • 管理这些任务的可用性

命令模型

  • ICommand 接口
    • Execute 方法
    • CanExecute 方法
    • CanExecuteChanged 事件
  • RoutedCommand 类
    • 实现了 ICommand 接口
    • Name 属性
  • RoutedUICommand 类
    • RoutedCommand 类的子类
    • Text 属性

执行命令

命令的绑定(Command=)

  • 命令事件未响应时,命令不可用,所绑定的控件也不可用
  • Executed 事件
  • CanExecute 事件

命令的执行

  • 调用指定命令对象的 Execute 方法
  • 调用 CommandBindings 集合中某个元素的 Execute 方法

数据验证(Validation)

INotifyDataErrorInfo 接口

要对数据对象进行数据验证,数据对象必须实现 INotifyDataErrorInfo 接口,该接口包含以下三个成员。

  • ErrorsChanged 事件(错误增加或减少时)
  • HasErrors 属性(数据对象是否有错误)
  • GetErrors 方法(返回所有错误的信息)

自定义验证规则(Custom Validation Rules)

  • 通过继承 ValidationRule 类并重写 Validate 方法可以实现自定义验证规则
  • 自定义验证规则可以加入到控件的 Binding.ValidationRules 集合中以实现对单一控件的数据验证
  • 自定义验证规则可以加入到容器的 BindingGroup.ValidationRules 集合中以实现对多个控件的集体验证
  • 验证规则在数据转换之前执行,只有验证规则通过后才进行数据转换
  • 验证规则可以有多条,依照先后顺序来执行

提示验证错误

  • 当控件的 Binding.NotifyOnValidationError 属性为 true 时,控件验证出错时会触发 Error 事件。
  • 控件的 ValidationError.ErrorContent 属性包含了错误信息。
  • 控件的 Validation.HasError 属性提示该控件是否出错
  • 控件的 Validation.ErrorTemplate 属性定义了出错时的提示性界面,覆盖该属性可实现自定义提示性界面。

自定义控件(UserControl 子类)

  • 自定义控件(UserControl 子类)向外界暴露的可绑定的属性必须是依赖属性
  • 自定义控件(UserControl 子类)所定义的路由事件必须是依赖属性
  • 顶层的 UserControl 标签中不应该定义 Name 属性,否则该属性将被暴露给控件的使用者
  • 顶层的 UserControl 标签中不应该使用 DataContext 属性,否则该控件的使用者所定义的 DataContext 属性将被覆盖
  • 为了方便自定义控件(UserControl 子类)自身子控件的绑定,可以在 UserControl 标签的直接下级子标签(比如 Grid)中使用 DataContext 属性
    WPF Binding to UserControl´s DependencyProperty not working as expected [duplicate]
    WPF UserControl Binding Problem

链接

Awesome WPF

原文地址:https://www.cnblogs.com/zwvista/p/9692575.html