@TOC


前言

做项目的时候,用到了WPF,总结下来,供以后参考,与诸君共勉。

一、Windows Presentation Foundation (WPF)

1.先补个作业:

  • Windows Presentation Foundation (WPF) ,Windows呈现基础,是微软新发布的Vista操作系统的三个核心开发库之一,是微软推出的基于Windows Vista的用户界面框架,属于. NET Framework 3.0的一部分。

2.WPF 主要编程模型编写。

  • 在WPF主要组件中:(PresentationFramework、PresentationCore 和 milcore)是 WPF 的主要代码部分
    • PresentationFramework
      • 托管组件【托管代码就是执行过程交由运行时管理的代码, 在这种情况下,相关的运行时称为公共语言运行时 (CLR),不管使用的是哪种实现(例如 Mono、.NET Framework 或 .NET Core/.NET 5+)。 CLR 负责提取托管代码、将其编译成机器代码,然后执行它。 除此之外,运行时还提供多个重要服务,例如自动内存管理、安全边界和类型安全。】
    • PresentationCore
      • 托管组件
    • milcore
      • 非托管组件
        • milcore 是以非托管代码编写的,目的是实现与 DirectX 的紧密集成。

3.WPF 中的所有显示均通过 DirectX 引擎完成

4.WPF 中的大多数对象派生自 DispatcherObject

5.System.Windows.DependencyObject

  • 生成 WPF 时使用的主要体系结构原理之一是首选属性而不是方法或事件。
    • 属性具有声明性,可更方便地指定用途而不是操作。它还支持模型驱动或数据驱动的系统,以显示用户界面内容。 这种理念的预期效果是创建更多可以绑定到的属性,从而更好地控制应用程序的行为。
  • WPF 提供一个更丰富的属性系统,该属性系统从 DependencyObject 类型派生。 该属性系统实际是一个“依赖”属性系统,因为它会跟踪属性表达式之间的依赖关系,并在依赖关系更改时自动重新验证属性值。
    • 比如,如果具有一个可继承的属性(如 FontSize),当继承该值的元素的父级发生属性更改时,系统会自动更新。
    • 属性系统还提供属性值的稀疏存储。 因为对象可能有数十个(如果达不到上百个)属性,并且大部分值处于其默认状态(被继承、由样式设置等),所以并非对象的每个实例都需要具有在其上定义的每个属性的完全权重。
    • 属性系统的最后一个新功能是附加属性的概念。 WPF 元素是基于组合和组件重用的原则生成的。 某些包含元素(如 Grid 布局元素)通常需要子元素上的其他数据才能控制其行为(如行/列信息)。 任何对象都可以为任何其他对象提供属性定义

6.System.Windows.Media.Visual

  • 定义一个系统后,下一步是将像素绘制到屏幕上。 Visual 类用于生成视觉对象的树,每个树可以选择性地包含绘制指令以及有关如何呈现这些指令(剪裁、转换等)的元数据。
  • Visual 实际上是 WPF 复合系统的入口点
  • WPF 通过遍历由 milcore 管理的非托管数据结构来显示数据。 这些结构(称为组合节点)代表层次结构显示树,其中每个节点都有呈现指令。 只能通过消息传递协议来访问此树
  • 在图形方面,WPF 使用保留呈现系统。
    • 这可以实现以高刷新率重绘系统
    • 并且组合系统不会阻止对用户代码的回调
  • WPF 使用“绘画器的算法”绘制模型
    • 要求每个组件从显示内容的背面绘制到正面,而不是剪裁每个组件。
    • 这允许每个组件在先前组件的显示内容上绘制。 此模型的优点是可以生成部分透明的复杂形状。 通过使用当今的新式图形硬件,此模型的速度相对较快

7.System.Windows.UIElement

  • UIElement 定义核心子系统,包括布局、输入和事件
    • 布局是 WPF 中的核心概念
      • 比如,(HTML 支持三种布局模型:流、绝对和表)
  • UIElement 还引入了 CommandBindings 的概念。 WPF 命令系统允许开发人员以命令终结点(一种用于实现 ICommand 的功能)的方式定义功能。

二、数据模型(属性)、交互模型(命令和事件)及显示模型(模板)之间的划分,可实现对控件的外观和行为的完全自定义

  • WPF 中数据绑定的最值得关注的功能之一是引入了数据模板。
    • 控件的最重要功能是模板化。
      • 如果将 WPF 的组合系统视为一个保留模式绘制系统,则控件可通过模板化以一种参数化的声明性方式描述其绘制。
      • 控件模板是 WPF 样式和模板模型提供的众多功能之一。
        • 在许多情况下不需要编写自己的控件。
      • ControlTemplate 实际上只是用于创建一组子元素的脚本,绑定到由控件提供的属性。
        • ControlTemplate旨在成为一个独立的实现细节单元,对外部用户和对象(包括样式)不可见。操作控件模板内容的唯一方法是在同一控件模板内。
      • Control 提供一组常用属性,例如 Foreground、Background、Padding,模板作者可以使用这些常用属性来自定义控件的显示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//调度对象 Scheduling object -> 框架模板 frame template -> 控制模板 control template
//设置Button的ControlTemplate的Button Style:
<Style TargetType="Button">
<!--Set to true to not get any properties from the themes.-->
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
//当咱们将控件的Template属性设置为新的ControlTemplate(如上例所示)时,咱们需要将替换整个模板。按钮获得焦点或按下时的外观都是要替换的按钮的默认外观的一部分。因此,根据需要,可能需要在定义中添加按下按钮时的外观
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight"
Value="23" />
<Setter Property="MinWidth"
Value="75" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border TextBlock.Foreground="{TemplateBinding Foreground}"
x:Name="Border"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>

</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
<VisualTransition GeneratedDuration="0"
To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource PressedBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource PressedBorderLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefault"
Value="true">

<Setter TargetName="Border"
Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource DefaultBorderBrushLightBrush}"
Offset="0.0" />
<GradientStop Color="{DynamicResource DefaultBorderBrushDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>

</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

  • 控件的实现提供了数据模型和交互模型。
    • 交互模型定义了一组命令(如窗口的“关闭”),以及到输入笔势的绑定(如单击窗口右上角的红叉)。
    • 数据模型提供了一组属性,用于自定义交互模型或自定义显示内容(由模板确定)。
      • 最常见的控件数据模型是内容模型。
    • 利用数据模板,可以通过声明方式指定某个数据片断的可视化方式。无需创建可绑定到数据的自定义用户界面,而是转而让数据来确定要创建的显示内容。
    • 样式实际上是轻量型的数据绑定。 使用样式,可以将共享定义的一组属性绑定到元素的一个或多个实例。

三、Windows Presentation Foundation (WPF) 实现 XAML 处理器实现并提供 XAML 语言支持

……开个头,继续看


巨人的肩膀