Spiga

WPF学习笔记4:控件模版

2021-08-29 16:36:24

一、WPF控件的组成

1. 逻辑与呈现的分离

​ 控件模板旨在成为展示详细信息的自包含单元,对外部用户和对象(包括 Style 对象)不可见。 操作控件模板内容的唯一方法是在当前控件模板中。

2. 模板修改:显示区域的内容重组

  • Button模板Template:渲染对象、属性值的关联、触发器
  • 样式与模板

3. 基础控件如何显示的?

  • 功能最强大,布局最灵活的容器

  • 主要属性配置:

    ColumnDefinitions(ColumnDefinition)、RowDefinitions(RowDefinition)、ShowGridLines、IsSharedSizeScope(SharedSizeGroup)、给子项控件使用:Grid.Row Grid.Column

  • 使用场景:广泛,不知道用什么布局,就用Grid,意外(WrapPanel)

二、模板中的基础控件

1. 基础元素的呈现:DrawingContext DrawRect

  • TextBlock
  • Border
  • OnRender

2. 控件模板案例解析

  • Label、GroupBox、CheckBox、RadioButton、ToggleButton
  • TextBox/PasswordBox、TabControl/TabItem、TreeView/TreeViewItem、ListBox/ListBoxItem、ListView/ListViewItem、Menu/MenuItem
  • ComboBox、ScrollViewer、ProgressBar、Slider
  • Calendar/DatePicker、DataGrid
  • 模板的添加与修改
  • 默认模板:wpf\src\Microsoft.DotNet.Wpf\src\Themes

3. 控件模板案例解析

  • 基本控件的使用
    • 名称、基本作用表现、特征
    • 常用属性:尺寸、定位、显示内容
    • 常用事件:点击、输入
  • 控件的特殊属性
    • Style:用来统一设置控件属性的对象
    • Resources:资源管理,存放可共用的数据(变量、样式、模板)
    • Template:用来控制控件的呈现
  • 目的:

三、属性与绑定

1. WPF的数据关系

绑定关系:数据绑定是应用呈现数据并与数据交互提供了一种简单而一致的方法,在应用 UI 与其显示的数据之间建立连接的过程。

2. 建立数据绑定关系的核心条件

  • 依赖对象 的 依赖属性
  • 依赖附加属性 (一个类型 只是使用方式不同,有一点所附加的对象需要是依赖对象)

3. 依赖属性的意义与作用

  • 核心模块
  • 内存共享,节省空间(同个类,不同实例中相同的属性默认值共享)
  • 数据绑定、样式、模板、动画。。。。
  • 如果没有依赖属性,WPF框架就是一个控件框架,相当于Winform

4. 依赖属性的定义

  • 基本过程:声明、注册、包装
  • 代码片段:propdp

5. 依赖属性的主要参数与回调方法

  • 默认值
  • 属性值变化回调、验证回调、强制回调
  • 元数据:FrameworkPropertyMetadataOptions

6. 依赖属性的继承

  • 允许元素树中的子元素从最近的父元素获取特定属性的值。
  • 由于父元素也可能通过属性值继承获得其属性值,因此系统可能递归回页面根。

7. 依赖附加属性的意义与作用

  • 给其它对象提供依赖属性功能
  • 有些对象的某些属性不能做绑定(PasswordBox)
  • 例子:布局控件做动态子项(ItemsControl-》布局控件放到容器模板)
  • 代码片段关键词:propa

8. 依赖附加属性的定义

  • 基本过程:声明、注册、包装
  • 依赖附加属性必须在依赖对象,附加属性不一定,关注的是被附加的对象是否是依赖对象

四、数据绑定

1. 关于数据绑定

  • Binding
  • 绑定:描述的是一种关系,通过某种关系将多个事物联系在一起
  • 通常情况下,每个绑定具有四个组件
    • 绑定目标对象。
    • 目标属性。
    • 绑定源。
    • 指向绑定源中要使用的值的路径。
  • 数据绑定的典型用法是将服务器或本地配置数据放置到窗体或其他 UI 控件中。不论要绑定什么元素,也不论数据源是什么性质,每个绑定都始终遵循下图所示的模型。

2. 数据绑定中的数据源

  • 指定方式:
    • DataContext-元素对象属性、(Source、ElementName、RelativeSource)-Binding对象内部属性
    • Path、XPath
  • 数据源类型:
    • 依赖对象做为数据源
    • 普通数据类型或集合类型做为数据源
    • 单个对象做为数据源(对象实例Source,Path=对象中的属性)
    • ADO.NET数据对象做为数据源
    • ObjectDataProvider做为数据源(Source=对象实例,Path=方法) 资源标签
    • Linq结果做为数据源 :List
    • XmlDataProvider做为数据源
    • 静态对象属性

3. 集合绑定与数据模板

  • -集合数据源:(ItemsControl\ListView\ListBox\DataGrid\ComboBox\TabControl\Menu\TreeView....)ItemsSource

  • 子项模板显示

  • 模板混合显示

    • 模板触发器
    • 模板选择器
  • 案例:直方图

    集合数据多级联动(省市区)

  • 不同集合控件的处理:

    1. ItemsControl、ListBox、ListView

    2. ListView、DataGrid

    3. TreeView

    4. 其他集合控件

3. 数据绑定对象Binding中的辅助属性

  • Mode
  • UpdateSourceTrigger
  • Converter、ConverterParemeter-(源与目标呈现数据类型不统一的时候)
  • StringFormat
  • Delay
  • FallbackValue:无法绑定的时候,显示一个默认值(XAML绑定失败窗口有错误)
  • TargetNullValue:数据源属性的值为null的时候目标属性中需要显示的信息
  • 验证与异常
    • Validation
    • ValidatesOnDataErrors

4. 绑定模式下的数据验证

  • ValidationRules
    • ExceptionValidationRule
    • 自定义ValidationRule
  • IDataErrorInfo
  • 正则表达式

5. 数据绑定方式扩展

  • 多重绑定:MultiBinding
    • MultValueConverter
    • 案例:动态传值,参与绑定运算
  • 优先级绑定:PriorityBinding
  • 移除绑定
    • 目标属性赋值
    • BindingOperations

五、对象事件

1. 事件无处不在

  • 委托的使用、执行时机
  • 生命周期事件(App)
  • 路由事件:(鼠标、键盘、拖拽、触控事件、Stylus、自定义路由事件)
  • 行为:事件的封装
2. 生命周期
  • App生命周期
    • Startup
    • Navigating、LoadCompleted、Navigated、NavigationFailed、NavigationProgress、NavigationStopped
    • SessionEnding
    • Activated、Deactivated
    • Exit
  • 全局异常捕获
    • DispatcherUnhandledException
    • AppDomain.CurrentDomain.UnhandledException
    • TaskScheduler.UnobservedTaskException

3. 输入事件

  • 鼠标输入事件:FrameworkElement:UIElement:Visual
    • Click-》WPF的Windows消息处理与Winform不一样
    • MouseEnter、MouseLeave、MouseDown、MouseUp、MouseMove、 MouseLeftButtonDown、MouseLeftButtonUp、MouseRightButtonDown、MouseRightButtonUp、MouseDoubleClick
    • Mouse.Capture
  • 键盘输入事件
    • KeyDown、KeyUp、TextInput 回车
    • TextChanged
  • 拖拽事件
    • Drop、DragLeave、DragOver、DragEnter
    • 触控事件与笔势(Stylus开头的事件)如果在触控设备中,鼠标事件时灵时不灵的时候,换Touch事件处理
      • Touch PreviewTouch Win7 Surface
      • 多点触控(Manipulation开头的事件),必须打开IsManipulationEnabled="True“
    • 自定义事件(普通事件)
      • 定义
      • 触发

4. 路由事件

  • 逻辑树与视觉树
  • 冒泡与隧道
    • MouseLeftButtonDown PreviewMouseLeftButtonDown
    • 逻辑处理逻辑 为什么需要
  • 自定义路由事件
    • 定义
    • 触发
    • 附加事件

5. 行为

  • 什么是行为?
    • 行为并不是WPF中的核心的部分,是Expression Blend的设计特性。使用行为的地方,也是可以使用触发器取代的。
    • 事件封装
  • 行为的使用

六、动画

1. 计算机动画

  • 补间动画:动画本质就是在一个时间段内对象尺寸、位移、旋转角度、缩放、颜色、透明度等属性值的连续变化。也包括图形变形的属性。时间、变化的对象、变化的值
  • 工业应用场景:蚂蚁线、旋转、高度变化、指针偏移、小车 起始-》结束 多长时间

2. WPF动画与分类

  • 特定对象处理动画过程。
  • 3大类共43个动画类:
    • 简单线性动画:18
    • 关键帧动画:22
    • 路径动画:3

| 简单线性动画 | ByteAnimation | ColorAnimation | DecimalAnimation | DoubleAnimation | | ------------------------------- | --------------------------------- | ----------------------------- | --------------------------------- | ---------------------------- | | Int16Animation | Int32Animation | Int64Animation | Point3DAnimation | | | PointAnimation | PopupAnimation | QuaternionAnimation | RectAnimation | | | Rotation3DAnimation | SingleAnimation | SizeAnimation | ThicknessAnimation | | | Vector3DAnimation | VectorAnimation | | | | | | | | | | | 关键帧动画 | BooleanAnimationUsingKeyFrames | ByteAnimationUsingKeyFrames | CharAnimationUsingKeyFrames | ColorAnimationUsingKeyFrames | | DecimalAnimationUsingKeyFrames | DoubleAnimationUsingKeyFrames | Int16AnimationUsingKeyFrames | Int32AnimationUsingKeyFrames | | | Int64AnimationUsingKeyFrames | MatrixAnimationUsingKeyFrames | ObjectAnimationUsingKeyFrames | Point3DAnimationUsingKeyFrames | | | PointAnimationUsingKeyFrames | QuaternionAnimationUsingKeyFrames | RectAnimationUsingKeyFrames | Rotation3DAnimationUsingKeyFrames | | | SingleAnimationUsingKeyFrames | SizeAnimationUsingKeyFrames | StringAnimationUsingKeyFrames | ThicknessAnimationUsingKeyFrames | | | Vector3DAnimationUsingKeyFrames | VectorAnimationUsingKeyFrames | | | | | | | | | | | 路径动画 | DoubleAnimationUsingPath | PointAnimationUsingPath | MatrixAnimationUsingPath | |

  • 动画类的选择
    • 根据属性类型确定
    • 变个大小、变个位置、变个颜色、变个显示(显示与隐藏)

3. 动画类基本使用

  • 创建类对象,设置相关属性,动画的执行

    • Duration、From、To
  • 动画的独立控制与整合

  • StoryBoard

    • 控制动画的运行:开始,停止,暂停,恢复
    • 动画与对象的桥梁:动画对象与页面对象的关联
    • MediaElement
  • 使用小结

    • 必须针对依赖属性
    • 对象必须派生自DependencyObject,并且实现Ianimatable接口
    • 必须存在可用的兼容动画类(支持自定义)
  • 关键帧动画 4大帧类型

    • Linear+【类型名称】+KeyFrame 线性变化关键帧,(简单线性动画的处理基本一样)
    • Discrete +【类型名称】+ KeyFrame 离散变化关键帧,不连续变化
    • Spline +【类型名称】+ KeyFrame 样条关键帧-》样条函数(二次贝塞尔曲线-Path)
    • Easing +【类型名称】+ KeyFrame 缓冲式关键帧,使用简单动画时介绍的缓动效果
    • ObjectAnimationUsingKeyFrames 理论让任意类型参与动画,只能离散形式的动画效果
  • 路径动画

    • 根据Path数据,限定动画路径
      • 类型名称+ AnimationUsingPath
      • 3个对象 Double、Point(X、Y)、Matrix(不需要记矩阵)
      • 路径Path
    • DoubleAnimationUsingPath:位移(TranslateTransform、Canvas LeftTop)、旋转(RoateTransform)
    • PointAnimationUsingPath:位移
    • MatrixAnimationUsingPath:合体,上面两个都包含

4. 动画对象的辅助属性

  • SpeedRatio:播放速度

  • AccelerationRatio:加速速率

  • DecelerationRatio:减速速率

  • AutoReverse:是否执行相反的动画

  • FillBehavior:动画结束状态:HoldEnd、Stop

  • RepeatBehavior:动画重复方式,包括三种值:Forever、次数、时间

    // 前面这些属性在Animation对象中也可以设置

  • IsAddtive:将目标属性的当前值添加到动画的起始值

  • IsCumulative:如果动画不断重复,就累积动画值

  • BeginTime:动画线启动等待时长

  • EasingFunction:动画缓动属性,EasingMode

  • BackEase、CircleEase、CubicEase、ElasticEase、ExponentialEase、PowerEase、QuadraticEase、QuarticEase、QuinticEase、SineEase

  • Timeline.DesiredFrameRate:设置帧率

5. 生命周期事件

  • Completed
  • CurrentGlobalSpeedInvalidated:速度变化
  • CurrentStateInvalidated:状态变化
  • CurretnTimeInvalidated:时间线

6. 动画控制

  • 动画的启动:事件、触发器、视觉管理器
  • 事件控制
    • BeginStoryboard:开始中一个故事板
    • PauseStoryboard:暂停
    • ResumeStoryboard:恢复
    • StopStoryboard:停止
    • SeekStoryboard:跳转某一帧,某个时刻
    • SetStoryboardSpeedRatio:加速、减速
  • 触发器控制
    • EnterActions
    • ExitActions
  • 视觉状态管理器
    • VisualState: 视图状态(Visual States)表示控件在一个特殊的逻辑状态下的样式、外观;
    • VisualStateGroup: 状态组由相互排斥的状态组成,状态组与状态组并不互斥;
    • VisualTransition: 视图转变 (Visual Transitions) 代表控件从一个视图状态向另一个状态转换时的过渡;
    • VisualStateManager: 由它负责在代码中来切换到不同的状态;
    • GoToState:针对控件模板中的视觉状态进行切换
    • GoToElementState:针对某个对象中的视觉状态进行切换

7. 案例实操

  • 菜单隐藏
  • 进度等待:
  • 机械臂控制:3D应用、平面
  • 蚂蚁线
  • 液面

七、控件自定义

1. 个性化处理的方式

  • 控件模板
  • UserControl 用户控件:日期时间选择器 DatePicker
  • CustomControl 自定义控件

2. UserControl与CustomControl

  • 开发方式与表现结构

  • CustomControl 模板与关键特性

  • 区别

    1. 自定义控件:注重控件对象的功能,必须遵守WPF的控件规则

      • 完全自己实现一个控件 继承现有控件进行功能扩展,并且添加新功能 WPF的控件要求
      • 后台代码(控制逻辑)和Generic.Xaml(样式 模板)进行组合
      • 支持模板重写
      • 继承Control
    2. 用户控件:注重复合控件组合使用,非常灵活,可以根据控件开发人员自己的意愿进行功能处理

      • 多个现有控件的集合,组成一个可复用的控件组
      • XAML和后台代码组成 绑定非常紧密
      • 不支持模板重写、样式
      • 继承UserControl

3. 开发案例

  • -期时间选择器
  • 数字框
  • 工业仪表
  • 各种常见开关
  • 工业应用场景组态
  • 另外的扩展:
    • 原生控件的模板修改,第三方库(很多)
    • 特殊的功能:功能比较多,性能控制不好,图表,第三方的图表库

4. 第三方控件库

  • UI控件库-HandyControl https://handyorg.github.io/

  • 图表控件库

    • LiveCharts:LiveCharts2预览版、内存管理不是很好,长时间持续更新的情况下,内存溢出,慎用

      数据加载量不能太大(1000点左右 开始卡)

    • ScottPlot:考虑性能, 建议这个 Nuget

    • OxyPlot

    • LightingChart