WPF概述
第一章主要介绍了WPF这个系统,具体的体系结构。
首先是WPF使用的图形引擎:DirectX,以及其拥有的优势:使用GPU处理;绘图操作效率更高;拥有更复杂的纹理映射、半透明效果。同时,WPF也保留了一个User32组件用于分屏以及处理和路由输入信息。
其次,为了保证WPF可以支持不同的分辨率以及系统DPI,WPF使用了矢量图代替位图,拥有分辨率无关性。
接下来是WPF的体系结构。
顶层 | PresentationFramework.dll | PresentationCore.dll | WindowsBase.dll | WPF API | 中间层 | milcore.dll | WindowsCodes.dll | | 媒体集成层 MIL | 底层 | Direct3D | User32 | | |
- PresentationFramework.dll:使用的大部分类,控件等
- PresentationCore.dll:所有的形状类和控件类,UIElement、VIsual等
- WindowBase.dll:基本要素,DespatcherObject、DependencyObject等
- milcore.dll:渲染系统的核心,将可视化元素转换成Direct3D可处理的三角形和纹理。
- WindowsCodes.dll:提供图像支持,如显示位图、JPEG图像等
然后是类的层次结构。通过WPF的核心继承树可以更好的理解整体代码的结构。
类 | DispatcherObject | DependencyObject | VIsual | UIElement | FrameworkElement | 内容 | 检查是否在线程上,调度管理 | 依赖属性特征 | 绘图支持 | 布局、输入、焦点、事件、路由、命令 | Margin等属性 |
类(布局元素) | Shape | Panel | Control | ContentControl | ItemsControl | 内容 | 形状类 | 布局容器 | 控件类(可交互的) | 单一内容控件 | 选项控件(列表控件等) |
XAML
XAML对于WPF并不是必须的,所以C#可以通过代码后置的方式去编写窗口。但XAML代码更直观,易读简单。
基础规则
接下来介绍的是XAML的基础规则,以一段代码为例。
<Window x:Class="CommonTool2.SelectWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CommonTool2"
mc:Ignorable="d"
Title="SelectWindow" Height="340" Width="320">
<Grid Height="300" Width="300">
</Grid>
</Window>
- Window:顶级元素,其余的顶级元素有Page以及Application。
- 名称空间:定义使用哪个Window类。
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 两者的区别:两个命名空间 -
类名隐藏:其实就是生成的新类。 <Window x:Class="CommonTool2.SelectWindow" 同时在cs文件中就会出现相应的类框架: namespace CommonTool2
{
public partial class SelectWindow : Window
{
public SelectWindow()
{
InitializeComponent();}}} 注意:InitializeComponent()方法,以及需要C#修改的需要添加命名元素x:Name。
简单属性
直接设置的属性,下面的是以TextBox为例。
<TextBox FontSize="24" VerticalAlignment="Stretch" Foreground="Green">
- 枚举类型:VerticalAlignment属性、HorizontalAlignment属性
- 字符串类型:FontFamily属性
- 整型:FontSize属性
- Brush对象:ForeGround属性
复杂属性
直接设置不了的属性,以Grid为例。
<Grid>
<Grid.Background>
……
</Grid.Background>
</Grid>
标记扩展
标记扩展其实我的理解就是使用其他资源设置属性的方法。
<Button Foreground="{x:Static ActiveCaptionBrush}">
代码后置的写法:
button.Foreground = SystemColors.ActiveCaptionBrush;
附加属性
附加属性就是类似Gird.Row="",为控件设置其他控件的属性的属性。
布局
布局容器:派生自Panel类,公有属性有Background、Children、IsItemsHost。包括StackPanel、WrapPanel、DockPanel、Grid、Canvas等。
布局属性:继承自FrameworkElement类。
Border控件:添加边框的控件,经常与布局面板一起使用。
布局舍入:因为Grid分辨率出现小数像素导致图像边缘模糊。解决方案:需要设置UseLayoutRounding属性为true。
共享尺寸:在顶级Grid元素中设置IsSharedSizeScope可以共享不同Grid的长宽尺寸。
Canvas:设备无关尺寸面板。
依赖项属性
这个用到的时候再细看吧。大约是定义、注册、验证、强制。
路由事件
其实也就是事件,只是会沿途传播。路由事件分为向上冒泡的路由事件以及向下隧道的路由事件。关于如何定义和注册路由事件:
public abstract class ButtonBase:……{
public static readonly RoutedEvent ClickEvent;//定义一个事件
static ButtonBase(){//注册事件
ButtonBase.ClickEvent = EventManager.RegisterRoutedEvent(……);
}
public event RoutedEventHandler Click{//事件封装器
add{
base.AddHandler(ButtonBase.ClickEvent,value);
}
remove{
base.RemoveHandler(ButtonBase.ClickEvent,value);
}
}
}
<Button MouseUp="Button_MouseUp">//将Button对象的MouseUp事件链接到Button_MouseUp事件处理程序
//也可以写成以下两种方式
Button.MouseUp +=Button_MouseUp;
Button.MouseUp +=new MouseButtonEventHandler(Button_MouseUp);
通用的事件都在UIElement类中,路由事件有三种方式:直接路由,冒泡路由,隧道路由。
RoutedEventArgs类
事件参数都会继承自这个类,可以获取一些事件相关的细节和信息。
代码示例1 冒泡路由事件
详见ExampleOne。
要点整理:
Click事件高于MouseUp以及MouseDown事件,遇到Click事件时会被挂起。
若想要某Panel面板下所有的Button都拥有同一个Click事件,可以在panel中添加附加属性,Button.Click="…",Button中的Tag属性就是用来在这种时候区分不同Button的。
代码示例2 隧道路由事件
WPF事件
事件分为以下五类:生命周期、鼠标、键盘、手写笔、多点触控。我重点看前三个。
生命周期事件
生命周期事件就是元素呗初始化、加载和卸载时发生的事件。所有元素的生命周期事件一共只有三种。
- Initialized:初始化的事件
- Loaded:初始化及样式应用、数据绑定后,发生的事件
- Unloaded:被释放时事件发生,窗口关闭或特定元素删除
Windows类的生命周期事件
键盘事件
键盘按键事件有五种:
- PreviewKeyDown:用于控制不会引发PreviewTextInput的按键,如空格。
- KeyDown:
- PreviewTextInput:用于控制输入,如只能输入数字,输入其他则设置handled标志。
- TextInput:
- PreviewKeyUp:
- KeyUp:
焦点用来控制某一控件,利用Tab进行焦点的切换。获取键盘状态的方法如下:
鼠标事件
鼠标移动事件:
- PreviewMouseMove:
- MouseMove:
- MouseEnter:
- MouseLeave:
- Mouse.Capture:当鼠标拖动离开当前元素时,需要捕获鼠标的位置和状态。
鼠标点击事件:
鼠标拖放事件:在System.Windows.DragDrop类中。
其他事件
触控、惯性等事件暂时用不到。 |