前言:
以下内容翻译自微软官方文档。
链接:https://docs.microsoft.com/zh-cn/dotnet/desktop-wpf/overview/
什么是WPF(Windows Presentation Foundation)
WPF是一个为Windows创建桌面客户端应用程序的UI框架。 WPF开发平台支持广泛的应用程序开发功能集,包括应用程序模型,控件,图形和数据绑定。 WPF使用可扩展应用程序标记语言(XAML)为应用程序编程提供声明性模型。
WPF有两种实现:
- 托管在 GitHub 上的开源实现。 此版本在.NET Core 3.0上运行。 用于XAML的WPF Visual Designer至少需要Visual Studio 2019 version 16.3.
- Visual Studio 2019和Visual Studio 2017支持的.NET Framework实现。
本桌面指南是为.NET Core 3.0和WPF编写的。 有关带有.NET Framework的WPF现有文档的更多信息,请参见Framework Windows Presentation Foundation.
XAML
XAML是WPF用于诸如定义资源或UI元素之类的基于XML的声明式语言。 XAML中定义的元素表示程序集中对象的实例化。 XAML与大多数其他标记语言不同,XAML在运行时进行解释,而无需直接绑定到支持类型系统。
以下示例显示了如何创建按钮作为UI的一部分。 本示例旨在让您了解XAML如何表示对象,其中Button是类型,而Content是属性。
<StackPanel>
<Button Content="Click Me!" />
</StackPanel>
XAML 扩展
XAML提供标记扩展的语法。 标记扩展可用于以属性形式,属性元素形式或同时以这两种形式提供属性值。
例如,先前的XAML代码定义了一个按钮,其可见内容设置为文字字符串“ Click Me!”,但是该内容可以由受支持的标记扩展设置。 标记扩展名由大括号{}和大括号{}定义。 然后,标记扩展名的类型由紧接在大括号后面的字符串令牌标识。
<StackPanel>
<Button Content="{MarkupType}" />
</StackPanel>
WPF为XAML提供了不同的标记扩展,例如用于数据绑定的{Binding}。
有关更多信息,请参见Markup Extensions and WPF XAML.
属性系统
WPF提供了一组服务,可用于扩展类型属性的功能。 这些服务统称为WPF属性系统。 WPF属性系统支持的属性称为依赖项属性。
依赖项属性通过提供支持属性的DependencyProperty类型来扩展属性功能。 依赖项属性类型是使用私有字段支持属性的标准模式的替代实现。
依赖属性
在WPF中,依赖项属性通常作为标准.NET属性公开。 从根本上讲,您可以直接与这些属性进行交互,而永远不会知道它们是作为依赖项属性实现的。
依赖项属性的目的是提供一种基于其他输入值来计算属性值的方法。 这些其他输入可能包括系统属性(例如主题和用户首选项),或者来自数据绑定和动画的即时属性。
可以实现依赖项属性来提供验证,默认值和监视其他属性更改的回调。 派生类还可以通过覆盖依赖项属性元数据,而不是创建新属性或覆盖现有属性,来更改现有属性的某些特定特征。
依赖对象
WPF属性系统的另一个关键类型是DependencyObject。 此类型定义可以注册并拥有依赖项属性的基类。 GetValue和SetValue方法为依赖项对象实例提供了依赖项属性的后备实现。
以下示例显示了一个依赖项对象,该对象定义了一个名为ValueProperty的依赖项属性标识符。 依赖项属性是使用Value .NET属性创建的。
public class TextField: DependencyObject
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(TextField), new PropertyMetadata(""));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
}
依赖项属性定义为依赖项对象类型的静态成员,例如上面的示例中的TextField。 依赖项属性必须在依赖项对象中注册。
上面示例中的Value属性包装了依赖项属性,提供了您可能习惯的标准.NET属性模式。
事件
WPF提供了一个事件系统,该系统位于您熟悉的.NET公共语言运行时(CLR)事件之上。这些WPF事件称为路由事件。
路由事件是CLR事件,它由RoutedEvent类的实例支持并在WPF事件系统中注册。从事件注册获得的RoutedEvent实例通常保留为注册类的公共静态只读字段成员,因此拥有路由事件。通过重写CLR事件的添加和删除实现来实现与同名的CLR事件(有时称为包装事件)的连接。路由事件支持和连接机制在概念上类似于Dependency属性是CLR属性的方式,该CLR属性由DependencyProperty类支持并在WPF属性系统中注册。
路由事件系统的主要优点是将事件泡在控制元素树上以寻找处理程序。例如,由于WPF具有丰富的内容模型,因此您将图像控件设置为按钮控件的内容。当您在图像控件上单击鼠标时,您希望它消耗鼠标事件,并因此中断命中测试,从而导致按钮调用Click事件。在传统的CLR事件模型中,您可以通过在图像和按钮上附加相同的处理程序来解决此限制。但是对于路由事件系统,在图像控件上调用的鼠标事件(例如选择它)会冒泡到父按钮控件。
数据绑定
WPF数据绑定为应用程序提供了一种简单一致的方式来呈现数据并与之交互。元素可以以公共语言运行时(CLR)对象和XML的形式绑定到来自不同类型数据源的数据。 WPF还提供了一种通过拖放操作进行数据传输的机制。
数据绑定是在应用程序UI和业务逻辑之间建立连接的过程。如果绑定具有正确的设置,并且数据提供了正确的通知,则当数据更改其值时,绑定到数据的元素会自动反映更改。数据绑定还可以意味着,如果元素中数据的外部表示发生更改,则基础数据将自动更新以反映该更改。例如,如果用户编辑TextBox元素中的值,则基础数据值将自动更新以反映该更改。
可以通过{Binding}标记扩展在XAML中配置数据绑定。下面的示例演示如何绑定到数据对象的ButtonText属性。如果该绑定失败,则用“Click Me!”
<StackPanel>
<Button Content="{Binding ButtonText, FallbackValue='Click Me!'}" />
</StackPanel>
UI 组件
WPF提供了几乎在每个Windows应用程序中使用的许多常见UI组件,例如Button,Label,TextBox,Menu和ListBox。 历史上,这些对象被称为控件。 尽管WPF SDK继续使用术语“控件”来粗略地表示应用程序中代表可见对象的任何类,但必须注意,无需为了继承可见类而从Control类继承该类。 从Control类继承的类包含ControlTemplate,该控件允许控件的使用者从根本上更改控件的外观,而无需创建新的子类。
样式和模板
WPF样式和模板指的是一系列功能(样式,模板,触发器和情节提要),这些功能允许应用程序,文档或UI设计器创建视觉上引人注目的应用程序并标准化其产品的特定外观。
WPF样式模型的另一个功能是表示和逻辑的分离,这意味着设计人员可以使用XAML处理应用程序的外观,而开发人员则可以在其他地方处理编程逻辑。
另外,了解资源很重要,这些资源使样式和模板可以重复使用。
资源
WPF资源是可以在应用程序中不同位置重用的对象。 资源的示例包括样式,模板和颜色笔刷。 资源可以用代码和XAML格式定义和引用。
每个框架级元素(FrameworkElement或FrameworkContentElement)都有一个Resources属性(它是ResourceDictionary类型),其中包含已定义的资源。 由于所有元素都继承自框架级元素,因此所有元素都可以定义资源。 但是,最常见的是在XAML文档的根元素上定义资源。