歡迎來到 Windows 簡報基礎桌面指南(WPF),這是一個與解析度無關、採用向量渲染引擎的 UI 框架,專為現代圖形硬體設計。 WPF 提供一組完整的應用程式開發功能,包括 Extensible Application Markup Language (XAML)、控制項、資料繫結、版面配置、2D 和 3D 圖形、動畫、樣式、範本、文件、媒體、文字,以及印刷樣式。 WPF 是 .NET 的一部分,因此您可以建置能納入 .NET API 其他元素的應用程式。
WPF 有兩種實作方式:
.NET 版本 (本指南):
裝載在 GitHub 上的 WPF 開放原始碼實作,它會在 .NET 上執行。 XAML 設計工具至少需要 Visual Studio 2019 16.8 版。 但根據您的 .NET 版本,您可能需要使用較新版本的 Visual Studio。
儘管 .NET 是一種跨平台技術,但 WPF 只能在 Windows 上執作。
.NET Framework 4 版本:
.NET Framework 的 WPF 實作,由 Visual Studio 2019 和 Visual Studio 2017 支援。
.NET Framework 4 是僅限 Windows 的 .NET 版本,並視為 Windows 作業系統元件。 此版本的 WPF 會隨 .NET Framework 一起分發。
本概觀適用於初學者,內容涵蓋 WPF 的主要功能和概念。 若要了解如何建立 WPF 應用程式,請參閱教學課程:建立新的 WPF 應用程式。
為什麼要從 .NET Framework 升級
當你將應用程式從 .NET Framework 升級到 .NET 時,你將受益於:
- 更好的效能
- 新的 .NET API
- 最新的語言改進
- 改善的可存取性與可靠性
- 更新的工具和更多的功能
要升級你的應用程式,請參考 「如何將 WPF 桌面應用程式升級為 .NET」。
使用 WPF 的程式
WPF 是 .NET 類型中的子集,這些類型大多位於 System.Windows 命名空間中。 如果你之前用 ASP.NET 和 Windows Forms 等框架用 .NET 建置應用程式,基本的 WPF 程式設計經驗應該很熟悉。 你:
- 將類別實體化
- 設定屬性
- 呼叫方法
- 處理事件
WPF 包含更多程式設計建構,可增強下列屬性和事件:相依性屬性和路由事件。
標記和後置程式碼
WPF 可讓您使用「標記語言」和「後置程式碼」來開發應用程式,這是 ASP.NET 開發人員應該很熟悉的功能。 您通常會使用 XAML 標記來實作應用程式的外觀,同時使用 Managed 程式設計語言 (程式碼後置) 來實作其行為。 將外觀與行為區隔開來的優點如下:
由於外觀特定標記未與行為特定程式碼緊密結合,因此可降低開發和維護成本。
由於實作應用程式外觀的設計人員可以與實作應用程式行為的設計人員同時進行,因此開發作業會更有效率。
WPF 應用程式的全球化與當地語系化已簡化。
標記
XAML 是以宣告方式來實作應用程式外觀的 XML 標記語言。 您通常可以使用它來定義視窗、對話方塊、頁面和使用者控制項,並填入控制項、圖案和圖形。
下列範例使用 XAML 來實作包含單一按鈕的視窗外觀:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Window with button"
Width="250" Height="100">
<!-- Add button to window -->
<Button Name="button">Click Me!</Button>
</Window>
具體來說,這個 XAML 會使用 Window 和 Button 項目來定義一個視窗和一個按鈕。 每個元素都會透過屬性進行設定,例如 Window 元素的 Title 屬性可指定視窗的標題列文字。 在執行階段,WPF 會將標記中定義的項目和屬性轉換成 WPF 類別的執行個體。 例如,Window 元素會轉換成 Window 類別的實例,其 Title 屬性即為 Title 屬性的值。
下圖顯示上述範例中 XAML 所定義的使用者介面 (UI):
由於 XAML 是基於 XML 的,你用它來組合的 UI 會以巢狀元素階層組成,稱為 元素樹。 項目樹狀結構提供一個邏輯和直覺方式來建立及管理 UI。
後端程式碼
應用程式的主要行為是實作相關功能以回應使用者互動。 例如,點擊選單或按鈕,並呼叫業務邏輯與資料存取邏輯作為回應。 在 WPF 中,這種行為是以與標記相關聯的程式碼實作的。 這種類型的程式碼稱為後置程式碼。 下列範例顯示更新自上一個範例的標記語法和程式碼後置檔案:
<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>
更新的標記會定義 xmlns:x 命名空間,並將其對應至結構描述,以新增對程式碼後置類型的支援。 屬性 x:Class 將程式碼背後的類別與此特定的 XAML 標記關聯起來。 考慮到這個屬性是在 <Window> 元素上宣告,程式碼後置類別必須繼承自 Window 類別,
using System.Windows;
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!");
}
}
}
Namespace SDKSample
Partial Public Class AWindow
Inherits System.Windows.Window
Public Sub New()
' InitializeComponent call is required to merge the UI
' that is defined in markup with this class, including
' setting properties and registering event handlers
InitializeComponent()
End Sub
Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Show message box when button is clicked.
MessageBox.Show("Hello, Windows Presentation Foundation!")
End Sub
End Class
End Namespace
InitializeComponent 從 code-behind 類別的建構子中呼叫,將標記中定義的 UI 與 code behind 類別合併。 (當系統建置您的應用程式時,會為您產生 InitializeComponent,因此您不需要手動實作)。x:Class 和 InitializeComponent 的組合可確保實作建立時獲得正確初始化。
請注意,在標記中,<Button> 項目會為 button_Click 屬性定義 Click 的值。 當標記和程式碼後台初始化並一起運作時,按鈕的 Click 事件會自動對應至 button_Click 方法。 當按鈕被點擊時,事件處理器會被呼叫,並透過呼叫 System.Windows.MessageBox.Show 該方法顯示訊息框。
下圖顯示按下按鈕的結果:
輸入和命令
控制項最常用來偵測及回應使用者輸入。 WPF 輸入系統 使用直接和路由事件來支援文字輸入、焦點管理和滑鼠定位。
應用程式通常具有複雜的輸入需求。 WPF 提供一個命令系統,將使用者輸入動作與回應這些動作的程式碼區隔開。 命令系統允許多個來源叫用相同的命令邏輯。 例如,假設是不同應用程式所使用的常見編輯作業:複製、剪下和貼上。 如果這些操作是用指令實作,可以用不同的使用者動作來呼叫。
控制項
應用模型透過建構的控制元件提供使用者體驗。 在 WPF 中,「控制項」是一個籠統詞彙,適用於具有下列特性的 WPF 類別分類:
- 裝載於視窗或頁面。
- 具有使用者介面。
- 實作一些行為。
如需詳細資訊,請參閱「控制項」。
依功能列出 WPF 控制項
以下列出內建 WPF 控制項:
按鈕: Button 和 RepeatButton。
日期顯示與選擇:Calendar 和 DatePicker。
對話方塊: OpenFileDialog、PrintDialog、和 SaveFileDialog。
數位墨水:InkCanvas 和 InkPresenter。
文件: DocumentViewer(文件檢視器)、 FlowDocumentPageViewer(流程文件頁面檢視器)、 FlowDocumentReader(流程文件閱讀器)、 FlowDocumentScrollViewer(流程文件滾動檢視器)和 StickyNoteControl(便利貼控制項)。
輸入: TextBox、 RichTextBox和 PasswordBox。
佈局: Border、 BulletDecorator、 Canvas、 DockPanel、 Expander、 Grid、 GridView、 GridSplitter、 GroupBox、 Panel、 ResizeGrip、 Separator、 ScrollBar、 ScrollViewer、 StackPanel、 Thumb、 Viewbox、 VirtualizingStackPanel、 Window和 WrapPanel。
媒體 :, , 和 。 選單: ContextMenu、Menu 和 ToolBar。
巡覽:Frame、Hyperlink、Page、NavigationWindow和TabControl。
選擇:CheckBox、ComboBox、ListBox、RadioButton和Slider。
使用者資訊: AccessText、 Label、 Popup、 ProgressBar、 StatusBar、 TextBlock和 ToolTip。
版面配置
當您建立使用者介面時,您可依位置和大小排列控制項,以形成一個版面配置。 所有版面配置的一個關鍵需求是隨視窗大小和顯示設定的變更進行調整。 WPF 不需強迫你撰寫程式碼來調整版面配置,而是提供一套一流的、可擴充的版面系統。
這個版面配置系統是以相對定位為基礎,藉此提升依視窗和顯示狀況變更來做調整的能力。 此外,這個版面配置系統可管理控制項之間的交涉,以決定版面配置。 此協商為兩個步驟的過程:首先,控制項會告訴其父節點所需的定位和尺寸設定。 然後再由父代指示控制項其可擁有的空間。
版面配置系統透過基礎 WPF 類別暴露給子控制器。 WPF 針對格線、堆疊和停駐等常見版面配置,提供了數個版面配置控制項:
Canvas:子控制項會提供自己的版面配置。
DockPanel:子控制項會沿著面板邊緣對齊。
Grid:子控制項會根據資料列和資料行定位。
StackPanel:子控制項會垂直或水平堆疊。
VirtualizingStackPanel:子控制項被虛擬化並依水平或垂直方向排列於單行。
WrapPanel:子控制項會以從左到右的順序定位,並在目前行沒有足夠空間時換行到下一行。
下列範例使用 DockPanel 來配置多個 TextBox 控制項:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.LayoutWindow"
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 中,由父控制項實作並供子控制項使用的屬性稱為附加屬性。
下圖顯示上述範例中的 XAML 標記結果:
數據系結
大多數應用程式提供使用者查看和編輯資料的手段。 對於 WPF 應用程式,許多不同的 .NET 資料存取函式庫,如 SQL 和 Entity Framework Core,已經提供資料儲存與存取的工作。 存取資料並將資料載入應用程式的管理物件之後,WPF 應用程式的重大工作才會開始。 基本上,這涉及兩個動作:
將受管理物件的資料複製到控制項,使用者可在此顯示與編輯資料。
確保使用控制項對資料所做的變更會被複製回受管理物件。
為了簡化應用程式開發工作,WPF 提供強大的資料繫結引擎以自動處理這些步驟。 資料繫結引擎的核心單位是 `Binding` 類別,其工作是將控制項(繫結目標)繫結至資料物件(繫結來源)。 下圖說明這個關聯性:
WPF 支援直接在 XAML 標記中宣告繫結。 例如,下列 XAML 程式碼會使用 "Text" XAML 語法,將 TextBox 的 Name 屬性繫結至物件的 {Binding ... } 屬性。 這是假設有一個資料物件被設置為 DataContext 的屬性,而 Window 具有一個 Name 屬性。
<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>
WPF 資料綁定引擎不僅提供綁定功能;它提供驗證、排序、篩選與分組功能。 此外,資料繫結支援使用資料範本來建立繫結資料的自訂使用者介面。
如需詳細資訊,請參閱資料繫結概觀。
圖形與動畫
WPF 提供一組廣泛又靈活的圖形功能,其優點如下:
解析度獨立與裝置獨立圖形。 WPF 圖形系統的基本測量單位是與裝置無關的畫素,這是一個 1/96 英吋的單位,為不受解析度和裝置影響的轉譯提供了基礎。 每個裝置獨立畫素會依轉譯所在系統的 DPI (每英吋的點數) 設定來自動調整。
改進精確度。 WPF 座標系統是使用雙精確度浮點數進行測量,而不是單精確度。 轉換和透明度值也會以雙精度來表示。 WPF 也支援廣色域 (scRGB),並提供整合式支援,以管理來自不同色彩空間的輸入。
進階圖形和動畫支援: WPF 可為您管理動畫場景以簡化圖形程式設計;您不需要擔心場景處理、轉譯迴圈和雙線性插補。 此外,WPF 還提供叫用測試支援和完整的 alpha 複合支援。
硬體加速 WPF 圖形系統利用圖形硬體將 CPU 使用量降到最低。
2D 圖形
WPF 提供以通用向量繪製的 2D 圖形圖庫,例如矩形和橢圓形。 圖形不僅用於顯示,還可實作許多您預期控制項會有的功能,包括鍵盤和滑鼠輸入。
WPF 提供的 2D 圖形涵蓋一組標準的基本圖形。 不過,你可能需要創建自訂形狀來協助設計客製化使用者介面。 WPF 提供幾何形狀來建立自訂圖形,您可以直接繪製、作為筆刷來使用,或是用來裁剪其他圖形和控制項。
如需詳細資訊,請參閱幾何概觀。
WPF 2D 功能子集包含漸層、點陣圖、繪圖、利用視訊繪製、旋轉、縮放和傾斜等視覺效果。 畫筆能達到所有這些效果。 下圖示範幾個範例:
如需詳細資訊,請參閱 WPF 筆刷概觀。
3D 渲染
WPF 也包含可與 2D 圖形互動的 3D 轉譯功能,以便建立更生動有趣的使用者介面。 例如,下圖顯示轉譯成 3D 圖形的 2D 影像:
如需詳細資訊,請參閱 3D 圖形概述。
動畫
WPF 動畫支援讓你可以讓控制項成長、搖晃、旋轉和淡出,創造有趣的頁面轉換等效果。 您可以建立大多數 WPF 類別的動畫,甚至是自訂類別。 下圖顯示簡單動畫的實際運作方式:
如需詳細資訊,請參閱動畫概觀。
文字和印刷樣式
為了確保高品質文字轉譯,WPF 提供下列功能:
- OpenType 字型支援。
- ClearType 增強功能。
- 利用硬體加速的高效能。
- 將文字與媒體、圖形和動畫進行整合。
- 國際字型支援和後援機制。
為了示範文字與圖形的整合,下圖顯示文字裝飾的應用:
如需詳細資訊,請參閱《Windows Presentation Foundation 中的印刷樣式》。
自訂 WPF 應用程式
到目前為止,您已經了解用於開發應用程式的核心 WPF 建置組塊:
- 您可以使用應用程式模型,來裝載及傳遞主要由控制項所組成的應用程式內容。
- 若要簡化使用者介面中控制項的排列方式,您可以使用 WPF 版面配置系統。
- 您可以使用資料繫結來減少使用者介面與資料整合的工作。
- 若要改進應用程式的視覺外觀,您可以使用的 WPF 所提供的各種圖形、動畫和媒體支援。
不過,這些基本功能通常並不足以建立及管理與眾不同且具有豐富視覺效果的使用者介面。 標準 WPF 控制項可能未與應用程式所需的外觀進行整合。 資料可能無法以最有效的方式顯示。 你的應用程式整體使用者體驗可能不適合 Windows 主題的預設外觀與感覺。
基於這個理由,WPF 提供各種機制來建立獨特的使用者體驗。
內容模型
大多數 WPF 控制項的主要用途在於顯示內容。 在 WPF 中,可構成控制項內容的項目類型和數目,稱為控制項的 「內容模型」(Content Model)。 某些控制項可能包含單一項目和內容類型。 例如,TextBox 變數的內容是一個指派給屬性 Text 的字串值。
不過,其他控制項可能包含不同內容類型的多個項目;Button 屬性所指定的 Content 內容可包含各種項目,包括版面配置控制項、文字、影像和圖形。
關於各種控制措施所支援的內容類型,請參見 WPF 內容模型。
觸發器
雖然 XAML 標記的主要目的是要實作應用程式的外觀,您也可以使用 XAML 來實作某些方面的應用程式行為。 其中一個範例是使用觸發程序,根據使用者互動來變更應用程式的外觀。 如需詳細資訊,請參閱樣式和範本。
範本
其他控制項與圖形通常構成 WPF 控制項的預設使用者介面。 例如,Button 是由 ButtonChrome 和 ContentPresenter 控制項所組成。 ButtonChrome 提供標準按鈕外觀,而 ContentPresenter 則顯示 Content 屬性所指定的按鈕內容。
有時控制項的預設外觀可能與整個應用程式的外觀產生衝突。 此時,使用 a ControlTemplate 來改變控制項使用者介面的外觀,但不改變其內容與行為。
例如,按一下 Button 時會引發 Click 事件。 只要改變按鈕的模板來顯示形狀 Ellipse ,控制的視覺面會改變,但功能本身不會改變。 您還是可以按一下控制項的視覺外觀,Click 事件也會如預期般引發。
資料範本
控制項範本可讓您指定控制項的外觀,而資料範本則可讓您指定控制項內容的外觀。 資料範本通常可用來增強繫結資料的顯示方式。 下圖顯示綁定於一組ListBox物件的預設外觀Task,每個任務都有名稱、描述和優先順序:
預設外觀是你對 ListBox 一貫的期待。 不過,每項工作的預設外觀只包含工作名稱。 要顯示任務名稱、描述和優先順序,請使用 DataTemplate 來改變ListBox 控制項綁定清單項目的預設外觀。 這裡有一個應用於 Task 物件的資料範本範例。
ListBox 會保留其行為和整體外觀,而僅有清單方塊所要顯示的內容外觀已變更。
如需更多資訊,請參閱資料範本化概覽。
樣式
樣式可讓開發人員和設計人員標準化其產品的特定外觀。 WPF 提供強大的樣式模型,其基礎是 Style 元素。 樣式可以將屬性值套用至類型。 樣式可以根據參考的類型或個別物件,自動套用至所有項目。 下列範例會建立一個樣式,以將視窗上每一個 Button 的背景色彩設定為 Orange:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.StyleWindow"
Title="Styles">
<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="SDKSample.ResourcesWindow"
Title="Resources Window">
<!-- 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>
</Window>
如需詳細資訊,請參閱如何定義及參考 WPF 資源。
自訂控制項
雖然 WPF 提供許多自訂支援,但是您可能還是會遇到現有 WPF 控制項不符合應用程式或其使用者需求的情況。 這種情況的發生原因包括:
- 您無法藉由自訂現有 WPF 實作的外觀和風格,來建立所需的使用者介面。
- 現有 WPF 實作不支援 (或無法輕易支援) 您需要的行為。
不過在這種情況下,您可以利用三種 WPF 模型之一來建立新的控制項。 每個模型各有適用的特定情況,並要求您的自訂控制項衍生自特定 WPF 基底類別。 以下列出這三種模型:
使用者控制項模型
自訂控制項衍生自 UserControl 並由一或多個其他控制項所組成。控制項模型自訂控制項衍生自 Control,並使用範本來建置實作以區隔其行為和外觀,與大多數 WPF 控制項非常類似。 衍生自 Control 比使用者控制項更能讓您自由地建立自訂使用者介面,但可能需要投入更多努力。
架構項目模型:
如果其外觀是由自訂的渲染邏輯(而不是範本)所定義,自訂控制項便衍生自 FrameworkElement。
如需自訂控制項的詳細資訊,請參閱控制項撰寫概觀。