学习课程摘自 MSDN/.net开发中的 WindowsPresentationFoundation
===1、概述===
WPF 的核心是一个与分辨率无关并且基于向量的呈现引擎,旨在利用现代图形硬件的优势。
WPF 通过一整套应用程序开发功能扩展了这个核心,这些功能包括 可扩展应用程序标记语言 (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。
WPF 包含在 Microsoft .NET Framework 中,使您能够生成融入了 .NET Framework 类库的其他元素的应用程序。
===2、WPF 标记和代码隐藏===
标记
XAML 是一种基于 XML 的标记语言,用于以声明的方式实现应用程序的外观。它通常用于创建窗口、对话框、页面和用户控件,并用控件、形状和图形填充它们。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.AWindow"
Title="Window with Button"
Width="250" Height="100">
<!-- Add button to window -->
<Button Name="button" Click="button_Click">Click Me!</Button>
</Window>
代码隐藏
应用程序的主要行为是实现响应用户交互的功能,包括处理事件(如,单击菜单、工具栏或按钮),并调用业务逻辑和数据访问逻辑作为响应。在 WPF 中,此行为通常在与标记关联的代码中实现。此类代码称为“代码隐藏”。
using System.Windows; // Window, RoutedEventArgs, MessageBox
namespace SDKSample
{
public partial class AWindow : Window
{
public AWindow()
{
// InitializeComponent call is required to merge the UI
// that is defined in markup with this class, including
// setting properties and registering event handlers
InitializeComponent();
}
void button_Click(object sender, RoutedEventArgs e)
{
// Show message box when button is clicked
MessageBox.Show("Hello, Windows Presentation Foundation!");
}
}
}
在此示例中,代码隐藏实现一个从 Window 类派生的类。
x:Class 属性用于将标记与代码隐藏类相关联。
InitializeComponent 是从代码隐藏类的构造函数中调用的,用于将标记中定义的 UI 与代码隐藏类相合并。
===3、应用程序===
WPF 提供了一些类型和服务,它们统称为“应用程序模型”。该应用程序模型既支持开发独立应用程序,也支持开发浏览器承载的应用程序。
独立应用程序
对于独立应用程序,您可以使用 Window 类创建可从菜单栏和工具栏上访问的窗口和对话框。
此外,您还可以使用以下 WPF 对话框: MessageBox、 OpenFileDialog、 SaveFileDialog 和 PrintDialog。.
浏览器承载的应用程序
对于浏览器承载的应用程序(称为 XAML 浏览器应用程序 (XBAP)),您可以创建能够使用超链接( Hyperlink 类)导航的页面 ( Page) 和页函数 ( PageFunction((T)))。
WPF 应用程序既可以承载于 Microsoft Internet Explorer 6 中,也可以承载于 Internet Explorer 7 中。WPF 提供了以下两个选项作为替代导航宿主:
Frame,用于承载页面或窗口中可导航内容的孤岛。
NavigationWindow,用于承载整个窗口中的可导航内容。
===4、布局===
布局系统的基础是相对定位,它提高了适应窗口和显示条件变化的能力。此外,布局系统还管理控件之间的协商以确定布局。
协商过程分为两步:第一步,控件向父控件通知它所需的位置和大小;第二步,父控件通知该控件它可以具有多大空间。
布局系统通过基本 WPF 类公开给子控件。对于通用的布局,如网格、堆叠和停靠,WPF 包括了几个布局控件:
Canvas:子控件提供其自己的布局。
DockPanel:子控件与面板的边缘对齐。
Grid:子控件按行和列放置。
StackPanel:子控件垂直或水平堆叠。
VirtualizingStackPanel:子控件被虚拟化,并沿水平或垂直方向排成一行。
WrapPanel:子控件按从左到右的顺序放置,如果当前行中的控件数多于该空间所允许的控件数,则换至下一行。
===5、数据绑定===
数据绑定引擎的核心单元是 Binding 类,它的任务是将控件(绑定目标)绑定到数据对象(绑定源)。
C# 复制代码
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.DataBindingWindow">
...
<!-- Bind the TextBox to the data source (TextBox.Text to Person.Name) -->
<TextBox Name="personNameTextBox" Text="{Binding Path=Name}" />
...
</Window>
------------------------------
namespace SDKSample
{
class Person
{
string name = "No Name";
public string Name
{
get { return name; }
set { name = value; }
}
}
}
--------------------------------
using System.Windows; // Window
namespace SDKSample
{
public partial class DataBindingWindow : Window
{
public DataBindingWindow()
{
InitializeComponent();
// Create Person data source
Person person = new Person();
// Make data source available for binding
this.DataContext = person;
}
}
}
-----------------------------------
在此示例中,Person 类在代码隐藏中实例化,并被设置为 DataBindingWindow 的数据上下文。
在标记中,将 TextBox 的 Text 属性绑定到 Person.Name 属性(使用“{Binding ... }”XAML 语法)。
此 XAML 通知 WPF 将 TextBox 控件绑定到存储在窗口的 DataContext 属性中的 Person 对象。
===6、===
图形 <Ellipse Name="clickableEllipse" Fill="Blue" MouseUp="clickableEllipse_MouseUp" />椭圆
动画
媒体
<MediaElement
Name="myMediaElement"
Source="media/wpf.wmv"
LoadedBehavior="Manual"
Width="350" Height="250" />
文本和版式
文档
WPF 本身支持使用三种类型的文档:流文档、固定文档和 XML 纸张规范 (XPS) 文档。WPF 还提供了用于创建、查看、管理、批注、打包和打印文档的服务。
流文档<FlowDocument/>
下面的示例演示如何将流文档加载到 FlowDocumentReader 中以进行查看、搜索和打印
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.FlowDocumentReaderWindow"
Title="Flow Document Reader">
<FlowDocumentReader Name="flowDocumentReader" />
</Window>
using System.Windows; // Window
using System.Windows.Documents; // FlowDocument
using System.IO; // FileStream, FileMode
using System.Windows.Markup; // XamlReader
namespace SDKSample
{
public partial class FlowDocumentReaderWindow : System.Windows.Window
{
public FlowDocumentReaderWindow()
{
InitializeComponent();
// Open the file that contains the FlowDocument
using (FileStream xamlFile = new FileStream("AFlowDocument.xaml",
FileMode.Open, FileAccess.Read))
{
// Parse the file with the XamlReader.Load method
FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;
// Set the Document property to the parsed FlowDocument object
this.flowDocumentReader.Document = content;//关联
}
}
}
}
===7、自定义WPF应用程序===
a、内容模型
TextBox 的内容为字符串值,该值被分配给 Text 属性
Button 的内容(由 Content 属性指定)可以包含各种项目,包括布局控件、文本、图像和形状。
<Button Margin="20">
<!-- Button Content -->
<DockPanel Width="200" Height="180">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center">Click Me!</Label>
<Border Background="Black" BorderBrush="Yellow" BorderThickness="2"
CornerRadius="2" Margin="5">
<MediaElement Source="media/wpf.wmv" Stretch="Fill" />
</Border>
</DockPanel>
</Button>
b、控件模板
WPF 控件的默认 UI 通常由其他控件和形状构造而来。例如,一个 Button 由 ButtonChrome 和 ContentPresenter 控件组成。
ButtonChrome 提供标准按钮外观,而 ContentPresenter 显示按钮的内容(由 Content 属性指定)。
有时控件的默认外观可能与应用程序的整体外观不一致。在这种情况下,您可以使用 ControlTemplate 更改控件的 UI 的外观,而无需更改控件的内容和行为。
<Button Content="Click Me!" Click="button_Click">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}"> ControlTemplate更改Button控件的 UI 的外观
<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>
c、数据模板
控件模板使您可以指定控件的外观,数据模板则允许您指定控件内容的外观。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.DataTemplateWindow"
Title="With a Data Template">
...
<!-- Data Template (applied to each bound task item in the task collection) -->
<DataTemplate x:Key="myTaskTemplate">
<Border Name="border" BorderBrush="DarkSlateBlue" BorderThickness="2"
CornerRadius="2" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Padding="0,0,5,0" Text="Task Name:"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Padding="0,0,5,0" Text="Description:"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Padding="0,0,5,0" Text="Priority:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
</Grid>
</Border>
</DataTemplate>
...
<!-- Data template is specified by the ItemTemplate attribute -->
<ListBox
ItemsSource="{Binding}"
ItemTemplate="{StaticResource myTaskTemplate}"
HorizontalContentAlignment="Stretch"
IsSynchronizedWithCurrentItem="True"
Margin="5,0,5,5" />
...
</Window>
d、样式
下面的示例创建一个样式,该样式将窗口中的每个 Button 的背景色设置为 Orange。
<!-- Style that will be applied to all buttons -->
<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>
e、资源
一个应用程序中的各控件应共享相同的外观,包括从字体和背景色到控件模板、数据模板和样式的所有方面。
您可以使用 WPF 对 用户界面 (UI) 资源的支持将这些资源封装到一个位置,以便于重复使用。
下面的示例定义一个通用的由 Button 和 Label 共享的背景色。
<!-- Define window-scoped background color resource -->
<Window.Resources>
<SolidColorBrush x:Key="defaultBackground" Color="Red" />
</Window.Resources>
...
<!-- 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>
资源和资源字典是 WPF 支持主题和外观的基础。
可以使用单独的 ResourceDictionary(可以在应用程序的其他部分引用)打包一个或多个资源
BackgroundColorResources.xaml文件内容:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Define background color resource -->
<SolidColorBrush x:Key="defaultBackground" Color="Red" />
<!-- Define other resources -->
...
</ResourceDictionary>
下面的示例引用上一个示例中定义的资源字典,从而在应用程序中共享。
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="BackgroundColorResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
...
</Application>
f、主题和外观
WPF 中的主题和外观都可以使用资源字典非常轻松地进行定义
g、自定义控件
目前您可以利用三个 WPF 模型之一创建一个新的控件。每个模型都针对一个特定的方案,并要求您的自定义控件从特定的 WPF 基类派生而来。此处列出了此三个模型:
用户控件模型。从 UserControl 派生的自定义控件,由其他一个或多个控件组成。
控制模型。从 Control 派生的自定义控件,用于生成使用模板将其行为和外观相分离的实现,与多数 WPF 控件非常相似。从 Control 派生使您可以比用户控件更自由地创建自定义 UI,但可能需要投入更多精力。
框架元素模型。从 FrameworkElement 派生的自定义控件,其外观由自定义呈现逻辑(而不是模板)定义。
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NumericUpDown">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- Value text box -->
<Border BorderThickness="1" BorderBrush="Gray" Margin="2" Grid.RowSpan="2"
VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
</Border>
<!-- Up/Down buttons -->
<RepeatButton Name="upButton" Click="upButton_Click" Grid.Column="1"
Grid.Row="0">Up</RepeatButton>
<RepeatButton Name="downButton" Click="downButton_Click" Grid.Column="1"
Grid.Row="1">Down</RepeatButton>
</Grid>
</UserControl>
-----------------------------
using System; // EventArgs
using System.Windows; // DependencyObject, DependencyPropertyChangedEventArgs,
// FrameworkPropertyMetadata, PropertyChangedCallback,
// RoutedPropertyChangedEventArgs
using System.Windows.Controls; // UserControl
namespace SDKSample
{
public partial class NumericUpDown : UserControl
{
// NumericUpDown user control implementation
...
}
}
-----------------------------
下一个示例演示将用户控件与 Window 合并所需的 XAML。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.UserControlWindow"
xmlns:local="clr-namespace:SDKSample"
Title="User Control Window">
...
<!-- Numeric Up/Down user control -->
<local:NumericUpDown />
...
</Window>