文章来源:
Windows Presentation Foundation - WPF .NET Framework
WPF 概述
Windows Presentation Foundation (WPF) 可以创建适用于 Windows 且具有非凡视觉效果的桌面客户端应用程序。
WPF 的核心是一个与分辨率无关且基于矢量的呈现引擎,旨在充分利用现代图形硬件。 WPF 通过一套完善的应用程序开发功能对该核心进行了扩展,这些功能包括可扩展应用程序标记语言 (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。 WPF 属于 .NET,因此可以生成整合 .NET API 其他元素的应用程序。
使用 WPF 进行编程
通过 WPF,可以使用标记和代码隐藏开发应用程序,这是 ASP.NET 开发人员已经熟悉的体验。
通常使用 XAML 标记实现应用程序的外观,同时使用托管编程语言C#/VB(代码隐藏)来实现其行为。
这种外观和行为的分离具有以下优点:
(1)降低了开发和维护成本,因为特定于外观的标记与特定于行为的代码不紧密耦合。
(2)开发效率更高,因为设计人员在实现应用程序外观的同时,开发人员可以实现应用程序的行为。
(3)WPF 应用程序的全球化和本地化 得以简化。
标记
XAML 是一种基于 XML 的标记语言,以声明形式实现应用程序的外观。 通常用它创建窗口、对话框、页和用户控件,并填充控件、形状和图形。
在运行时,WPF 会将标记中定义的元素和特性转换为 WPF 类的实例。
由于 XAML 是基于 XML 的,因此使用它编写的 UI 汇集在嵌套元素的层次结构中,称为 元素树。 元素树提供了一种直观的逻辑方式来创建和管理 UI。
代码隐藏
应用程序的主要行为是实现响应用户交互的功能,包括处理事件(例如,单击菜单、工具栏或按钮)以及相应地调用业务逻辑和数据访问逻辑。
在 WPF 中,在与标记相关联的代码中实现此行为。 此类代码称为代码隐藏。
**
<Window x:Class="Demo1.WPF介绍.MainWindow"
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:Demo1.WPF介绍"
mc:Ignorable="d"
Title="Window with Button" Height="450" Width="800">
<Button Name="button" Click="button_Click">Click Me!</Button>
</Window>
namespace Demo1.WPF介绍 {
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("Hello, Windows Presentation Foundation!");
}
}
}
x:Class 特性用于将标记与代码隐藏类相关联。 从代码隐藏类的构造函数调用 InitializeComponent,以将标记中定义的 UI 与代码隐藏类合并在一起。 (生成应用程序时即会生成 InitializeComponent,因此不需要手动实现它。)x:Class 和 InitializeComponent 的组合可确保在创建实现时正确地对其进行初始化。
控制
应用程序模型带来的用户体验是构造的控件。 在 WPF 中,控件是适用于 WPF 类这一类别的总括术语,这些类托管在窗口或页中、具有用户界面并实现一些行为。
输入和命令
最常检测和响应用户输入的控件。 WPF 输入系统 使用直接事件和路由事件来支持文本输入、焦点管理和鼠标定位。
应用程序通常具有复杂的输入要求。 WPF 提供了命令系统,用于将用户输入操作与对这些操作做出响应的代码分隔开来。
Layout
WPF 为你提供一流的可扩展布局系统,而不强制你编写代码以适应这些情况下的布局。布局系统的基础是相对定位,这提高了适应不断变化的窗口和显示条件的能力。
此外,该布局系统还可管理控件之间的协商以确定布局。 协商是一个两步过程:首先,控件将需要的位置和大小告知父级;其次,父级将控件可以有的空间告知控件。
该布局系统通过基 WPF 类公开给子控件。 对于通用的布局(如网格、堆叠和停靠),WPF 包括若干布局控件:
- Canvas:子控件提供其自己的布局。
- DockPanel:子控件与面板的边缘对齐。
- Grid:子控件由行和列定位。
- StackPanel:子控件垂直或水平堆叠。
- VirtualizingStackPanel:子控件在水平或垂直的行上虚拟化并排列。
- WrapPanel:子控件按从左到右的顺序定位,在当前行上的控件超出允许的空间时,换行到下一行。
示例:由父控件实现以便子控件使用的属性是 WPF 构造,称为附加属性。例如下例的Dock属性
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Layout with the DockPanel" Height="143" Width="319">
<!--DockPanel to layout four text boxes-->
<DockPanel>
<TextBox DockPanel.Dock="Top">Dock = "Top"</TextBox>
<TextBox DockPanel.Dock="Bottom">Dock = "Bottom"</TextBox>
<TextBox DockPanel.Dock="Left">Dock = "Left"</TextBox>
<TextBox Background="White">This TextBox "fills" the remaining space.</TextBox>
</DockPanel>
</Window>
DockPanel 允许子 TextBox 控件,以告诉它如何排列这些控件。 为了完成此操作,DockPanel 实现 Dock 附加了属性,该属性公开给子控件,以允许每个子控件指定停靠样式。
数据绑定
WPF 提供了一个数据绑定引擎来自动执行以下两个步骤。
- 将数据从托管对象复制到控件,在控件中可以显示和编辑数据。
- 确保使用控件对数据所做的更改将复制回托管对象。
数据绑定引擎的核心单元是 Binding 类,其工作是将控件(绑定目标)绑定到数据对象(绑定源)。
示例:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Binding" Height="143" Width="319">
<StackPanel>
<TextBox x:Name="tbox" Text="{Binding Path=Name}"/>
</StackPanel>
</Window>
namespace Demo1.WPF介绍 {
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
// 使数据源可用于绑定
this.DataContext=new Person();
}
}
class Person {
private string name = "No Name";
public string Name {
get { return name; }
set { name = value; }
}
}
}
WPF 数据绑定引擎提供了额外支持,包括验证、排序、筛选和分组。 此外,数据绑定支持在标准 WPF 控件显示的用户界面不恰当时,使用数据模板来为数据绑定创建自定义的用户界面。
显卡
WPF 引入了一组广泛、可伸缩的灵活图形功能,具有以下优点:
- 图形与分辨率和设备均无关。
- 精度更高。
- 高级图形和动画支持。
- 硬件加速。 WPF 图形系统充分利用图形硬件来尽量降低 CPU 使用率。
二维形状
形状的一个有趣功能是它们不只是用于显示;形状实现许多你期望的控件功能,包括键盘和鼠标输入。
WPF 提供一个常用矢量绘制的二维形状库,如下图中所示的矩形和椭圆:
示例:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Click the Ellipse" Height="143" Width="319">
<Ellipse Name="clickableEllipse" Fill="Blue" MouseUp="clickableEllipse_MouseUp" />
</Window>
namespace Demo1.WPF介绍 {
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void clickableEllipse_MouseUp(object sender, MouseButtonEventArgs e) {
MessageBox.Show("You clicked the ellipse!");
}
}
}
二维几何图形
WPF 提供的二维形状包含基本形状的标准集。 但是,你可能需要创建自定义形状以帮助改进自定义用户界面的设计。 为此,WPF 提供了几何图形。
Path 对象可用于绘制封闭式或开放式形状、多个形状,甚至曲线形状。
Geometry 对象可用于剪辑、命中测试以及呈现二维图形数据。
二维效果
WPF 二维功能的子集包括视觉效果,如渐变、位图、绘图、用视频绘画、旋转、缩放和倾斜。
这些效果都可以使用画笔实现 Brush
三维呈现
WPF 还包括三维呈现功能,这些功能与二维图形集成,以创建更精彩、更有趣的用户界面。
动画
WPF 动画支持可以使控件变大、抖动、旋转和淡出,以形成有趣的页面过渡等。 你可以对大多数 WPF 类,甚至自定义类进行动画处理。
媒体
传达丰富内容的一种方法是使用视听媒体。 WPF 为图像、视频和音频提供特殊支持。
图像
图像对大多数应用程序很常见,WPF 提供多种方式来使用它们。
视频和音频
**MediaElement **控件能够播放视频和音频,并且其足够灵活,可以用作其他自定义媒体播放器的基础。
文本和版式
为了促进高质量的文本呈现,WPF 提供以下功能:
- OpenType 字体支持。
- ClearType 增强功能。
- 利用硬件加速的高性能。
- 文本与媒体、图形和动画的集成。
- 国际字体支持和回退机制。
自定义 WPF 应用
在创建和管理真正独特且视觉效果非凡的用户体验时,基础知识通常是不够的。 标准的 WPF 控件可能无法与你所需的应用程序外观集成。 数据可能不会以最有效的方式显示。
为此,WPF 提供了多种机制用于创建独特的用户体验,包括控件、触发器、控件和数据模板、样式、用户界面资源以及主题和皮肤的丰富内容模型。
内容模型
大多数 WPF 控件的主要用途是显示内容。 在 WPF 中,可以构成控件内容的项的类型和数目称为控件的 内容模型。
某些控件可以包含一种内容类型的一个项。例如, TextBox 的内容是分配给 Text 属性的一个字符串值。
但是,其他控件可以包含不同内容类型的多个项。例如, Button的内容(由 Content 属性指定)可以包含各种项(包括布局控件、文本、图像和形状)。
触发器
尽管 XAML 标记的主要用途是实现应用程序的外观,你也可以使用 XAML 来实现应用程序行为的某些方面。 其中一个示例是使用触发器来基于用户交互更改应用程序的外观。
触发器在属性值发生更改或引发事件时设置属性或启动操作,例如动画。 Style、ControlTemplate 和 DataTemplate 都具有可包含一组触发器的 Triggers 属性。 触发器分为几种类型。
控件模板
WPF 控件的默认用户界面通常是从其他控件和形状构造的。
有时,某个控件的默认外观可能与应用程序的整体外观不一致。 在这种情况下,可以使用 ControlTemplate 更改控件的用户界面的外观,而不更改其内容和行为。
示例:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Button with Control Template" Height="143" Width="319">
<Button Content="Click Me!" Click="Button_Click">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Margin="5">
<Ellipse Stroke="DarkBlue" StrokeThickness="2">
<Ellipse.Fill>
<RadialGradientBrush Center="0.3,0.2" RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="Azure" Offset="0.1" />
<GradientStop Color="CornflowerBlue" Offset="1.1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter Name="content" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Window>
namespace Demo1.WPF介绍 {
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("Hello, Windows Presentation Foundation!");
}
}
}
数据模板
使用控件模板可以指定控件的外观,而使用数据模板则可以指定控件内容的外观。 数据模板经常用于改进绑定数据的显示方式。 DataTemplate
样式
通过样式功能,开发人员和设计人员能够对其产品的特定外观进行标准化。 WPF 提供了一个强样式模型,其基础是 Style 元素。
示例:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Styles" Height="143" Width="319">
<Window.Resources>
<!-- Style that will be applied to all buttons for this window -->
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange" />
<Setter Property="BorderBrush" Value="Crimson" />
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="5" />
</Style>
</Window.Resources>
<StackPanel>
<!-- This button will have the style applied to it -->
<Button>Click Me!</Button>
<!-- This label will not have the style applied to it -->
<Label>Don't Click Me!</Label>
<!-- This button will have the style applied to it -->
<Button>Click Me!</Button>
</StackPanel>
</Window>
资源
应用程序中的控件应共享相同的外观,它可以包括从字体和背景色到控件模板、数据模板和样式的所有内容。 你可以对用户界面资源使用 WPF 支持,以将这些资源封装在一个位置以便重复使用。
示例:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo1.WPF介绍.MainWindow"
Title="Resources Window" Height="143" Width="319">
<!-- Define window-scoped background color resource -->
<Window.Resources>
<SolidColorBrush x:Key="defaultBackground" Color="Red" />
</Window.Resources>
<StackPanel>
<!-- Button background is defined by window-scoped resource -->
<Button Background="{StaticResource defaultBackground}">One Button</Button>
<!-- Label background is defined by window-scoped resource -->
<Label Background="{StaticResource defaultBackground}">One Label</Label>
</StackPanel>
</Window>
此示例通过使用 Window.Resources 属性元素实现背景色资源。 此资源可供 Window的所有子级使用。
有各种资源作用域,具体如下(按解析顺序列出):
- 单个控件(使用继承的 System.Windows.FrameworkElement.Resources 属性)。
- Window 或 Page (也使用继承的 System.Windows.FrameworkElement.Resources 属性)。
- Application (使用 System.Windows.Application.Resources 属性)。
这些不同种类的作用域在定义和共享资源的方式方面为你提供了灵活性。
自定义控件
WPF 中可以充分利用三个 WPF 模型中的一个来创建新的控件。 每个模型都针对一个特定的方案并要求你的自定义控件派生自特定 WPF 基类。
- 用户控件模型。 自定义控件派生自 UserControl 并由一个或多个其他控件组成。
- 控件模型。 自定义控件派生自 Control ,并用于生成使用模板将其行为与其外观分隔开来的实现,非常类似大多数 WPF 控件。 派生自 Control 使得你可以更自由地创建自定义用户界面(相较用户控件),但它可能需要花费更多精力。
- 框架元素模型。 当其外观由自定义呈现逻辑(而不是模板)定义时,自定义控件派生自FrameworkElement