桌面指南 (WPF .NET)

歡迎使用 Windows Presentation Foundation (WPF) 桌面指南,這是一款不受解析度影響的 UI 架構,並使用以向量為基礎的轉譯引擎,專為利用新式圖形硬體的優勢量身打造。 WPF 提供一組完整的應用程式開發功能,包括 Extensible Application Markup Language (XAML)、控制項、資料繫結、版面配置、2D 和 3D 圖形、動畫、樣式、範本、文件、媒體、文字,以及印刷樣式。 WPF 是 .NET 的一部分,因此您可以建置能納入 .NET API 其他元素的應用程式。

重要

.NET 7 和 .NET 6 的桌面指南檔正在建置中。

WPF 有兩個實作:

  1. .NET 版本 (本指南):

    裝載於 GitHub 上的 WPF 開放原始碼實作,其會在 .NET 上執行。 XAML 設計工具至少需要 Visual Studio 2019 16.8 版。 但視您的 .NET 版本而定,您可能需要使用較新版本的Visual Studio。

    雖然 .NET 是跨平台技術,但 WPF 只會在 Windows 上執行。

  2. .NET Framework 4 版本:

    支援 Visual Studio 2019 和 Visual Studio 2017 的 WPF .NET Framework 實作。

    .NET Framework 4 是僅限 Windows 的 .NET 版本,並視為 Windows 作業系統元件。 此版本的 WPF 會隨 .NET Framework 散發。 如需 WPF 的 .NET Framework 版本詳細資訊,請參閱適用於 .NET Framework 的 WPF 簡介

本概觀適用於初學者,內容涵蓋 WPF 的主要功能和概念。 若要了解如何建立 WPF 應用程式,請參閱教學課程:建立新的 WPF 應用程式

為何從 .NET Framework 升級

當您將應用程式從 .NET Framework 升級至 .NET 時,您將受益於:

  • 更好的效能
  • 新的 .NET API
  • 最新的語言改進
  • 改善的輔助功能和可靠性
  • 已更新的工具和其他專案

若要瞭解如何升級您的應用程式,請參閱 如何將 WPF 傳統型應用程式升級至 .NET 7

使用 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 會使用 WindowButton 項目來定義一個視窗和一個按鈕。 每個項目都會透過屬性進行設定,例如 Window 項目的 Title 屬性可指定視窗的標題列文字。 在執行階段,WPF 會將標記中定義的項目和屬性轉換成 WPF 類別的執行個體。 例如, Window 項目會轉換成 Window 類別的執行個體,其 Title 屬性即為 Title 屬性的值。

下圖顯示上述範例中 XAML 所定義的使用者介面 (UI):

A window that contains a button

由於 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,以合併標記中定義的 UI 與程式碼後置類別 (當系統建置您的應用程式時,會為您產生 InitializeComponent,因此您不需要手動實作)。x:ClassInitializeComponent 的組合可確保實作建立時獲得正確初始化。

請注意,在標記中,<Button> 項目會為 Click 屬性定義 button_Click 的值。 當標記和程式碼後置初始化並一起運作時,按鈕的 Click 事件會自動對應至 button_Click 方法。 當您按一下按鈕時,即會呼叫 System.Windows.MessageBox.Show 方法來叫用事件處理常式,並顯示訊息方塊。

下圖顯示按下按鈕的結果:

A MessageBox

輸入和命令

控制項最常用來偵測及回應使用者輸入。 WPF 輸入系統 使用直接和路由事件來支援文字輸入、焦點管理和滑鼠定位。

應用程式通常具有複雜的輸入需求。 WPF 提供一個命令系統,將使用者輸入動作與回應這些動作的程式碼區隔開。 命令系統允許多個來源叫用相同的命令邏輯。 例如,假設是不同應用程式所使用的常見編輯作業:複製剪下貼上。 如果這些作業是使用命令實作,則可以使用不同的使用者動作來叫用這些作業。

控制項

應用程式模型所傳遞的使用者體驗是已建構的控制項。 在 WPF 中,「控制項」是一個籠統詞彙,適用於具有下列特性的 WPF 類別分類:

  • 裝載於視窗或頁面。
  • 具有使用者介面。
  • 實作一些行為。

如需詳細資訊,請參閱 控制項

依功能列出 WPF 控制項

以下列出內建 WPF 控制項:

版面配置

當您建立使用者介面時,您可依位置和大小排列控制項,以形成一個版面配置。 所有版面配置的一個關鍵需求是隨視窗大小和顯示設定的變更進行調整。 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 標記結果:

DockPanel page

資料繫結

大多數已建立的應用程式會為使用者提供檢視及編輯資料的方法。 針對 WPF 應用程式,儲存和存取資料的工作已經由許多不同 .NET 資料存取程式庫提供,例如 SQL 和 Entity Framework Core。 存取資料並將資料載入應用程式的 Managed 物件之後,才會開始 WPF 應用程式的困難工作。 基本上,這涉及兩個動作:

  1. 將資料從 Managed 物件複製到控制項,以在其中顯示及編輯資料。

  2. 確保使用控制項對資料所做的變更,會複製回 Managed 物件。

為了簡化應用程式開發工作,WPF 提供強大的資料繫結引擎以自動處理這些步驟。 資料繫結引擎的核心單位是 Binding 類別,其工作是將控制項 (繫結目標) 繫結至資料物件 (繫結來源)。 下圖說明這個關聯性:

Basic data binding diagram

WPF 支援直接在 XAML 標記中宣告繫結。 例如,下列 XAML 程式碼會使用 "{Binding ... }" XAML 語法,將 TextBoxText 屬性繫結至物件的 Name 屬性。 這是假設使用 Name 屬性將資料物件設為 WindowDataContext 屬性。

 <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 英吋的 1/96,可作為不受解析度與裝置影響的轉譯基礎。 每個裝置獨立畫素會依轉譯所在系統的 DPI (每英吋的點數) 設定來自動調整。

  • 改進精確度。 WPF 座標系統是使用雙精確度浮點數進行測量,而不是單精確度。 轉換和透明度值也會以雙精確度來表示。 WPF 也支援廣色域 (scRGB),並提供整合式支援,以管理來自不同色彩空間的輸入。

  • 進階圖形和動畫支援: WPF 可為您管理動畫場景以簡化圖形程式設計;您不需要擔心場景處理、轉譯迴圈和雙線性插補。 此外,WPF 還提供叫用測試支援和完整的 alpha 複合支援。

  • 硬體加速: WPF 圖形系統利用圖形硬體將 CPU 使用量降到最低。

2D 圖形

WPF 提供以通用向量繪製的 2D 圖形圖庫,例如矩形和橢圓形。 圖形不僅用於顯示,還可實作許多您預期控制項會有的功能,包括鍵盤和滑鼠輸入。

WPF 提供的 2D 圖形涵蓋一組標準的基本圖形。 不過,您可能需要建立自訂圖形,來協助自訂使用者介面的設計。 WPF 提供幾何形狀來建立自訂圖形,您可以直接繪製、作為筆刷來使用,或是用來裁剪其他圖形和控制項。

如需詳細資訊,請參閱幾何概觀

WPF 2D 功能子集包含漸層、點陣圖、繪圖、利用視訊繪製、旋轉、縮放和傾斜等視覺效果。 這些效果全都是使用筆刷來達成。 下圖示範幾個範例:

Illustration of different brushes

如需詳細資訊,請參閱 WPF 筆刷概觀

3D 轉譯

WPF 也包含可與 2D 圖形互動的 3D 轉譯功能,以便建立更生動有趣的使用者介面。 例如,下圖顯示轉譯成 3D 圖形的 2D 影像:

Visual3D sample screen shot

如需詳細資訊,請參閱 3D 圖形診斷

動畫

WPF 動畫支援可讓您將控制項設為放大、搖晃、旋轉和淡出,以建立有趣的網頁切換及執行其他工作。 您可以建立大多數 WPF 類別的動畫,甚至是自訂類別。 下圖顯示簡單動畫的實際運作方式:

Images of an animated cube

如需詳細資訊,請參閱動畫概觀

文字和印刷樣式

為了確保高品質文字轉譯,WPF 提供下列功能:

  • OpenType 字型支援。
  • ClearType 增強功能。
  • 利用硬體加速的高效能。
  • 將文字與媒體、圖形和動畫進行整合。
  • 國際字型支援和後援機制。

為了示範文字與圖形的整合,下圖顯示文字裝飾的應用:

Text with various text decorations

如需詳細資訊,請參閱 Windows Presentation Foundation 中的印刷樣式

自訂 WPF 應用程式

到目前為止,您已經了解用於開發應用程式的核心 WPF 建置組塊:

  • 您可以使用應用程式模型,來裝載及傳遞主要由控制項所組成的應用程式內容。
  • 若要簡化使用者介面中控制項的排列方式,您可以使用 WPF 版面配置系統。
  • 您可以使用資料繫結來減少使用者介面與資料整合的工作。
  • 若要改進應用程式的視覺外觀,您可以使用的 WPF 所提供的各種圖形、動畫和媒體支援。

不過,這些基本功能通常並不足以建立及管理與眾不同且具有豐富視覺效果的使用者介面。 標準 WPF 控制項可能未與應用程式所需的外觀進行整合。 資料可能不會以最有效的方式來顯示。 Windows 佈景主題的預設外觀和風格可能不適合您應用程式的整體使用者介面。

基於這個理由,WPF 提供各種機制來建立獨特的使用者體驗。

內容模型

大多數 WPF 控制項的主要用途在於顯示內容。 在 WPF 中,可構成控制項內容的項目類型和數目,稱為控制項的 「內容模型」(Content Model)。 某些控制項可能包含單一項目和內容類型。 例如,TextBox 的內容是指派給 Text 屬性的字串值。

不過,其他控制項可能包含不同內容類型的多個項目;Content 屬性所指定的 Button 內容可包含各種項目,包括版面配置控制項、文字、影像和圖形。

如需各種控制項所支援之內容類型的詳細資訊,請參閱 WPF 內容模型

觸發程序

雖然 XAML 標記的主要目的是要實作應用程式的外觀,您也可以使用 XAML 來實作某些方面的應用程式行為。 其中一個範例是使用觸發程序,根據使用者互動來變更應用程式的外觀。 如需詳細資訊,請參閱樣式和範本

範本

WPF 控制項的預設使用者介面通常是從其他控制項和圖案建構而來。 例如, Button 是由 ButtonChromeContentPresenter 控制項所組成。 ButtonChrome 提供標準按鈕外觀,而 ContentPresenter 則顯示 Content 屬性所指定的按鈕內容。

有時候,控制項的預設外觀可能與應用程式的整體外觀有衝突。 在這種情況下,您可以使用 ControlTemplate 變更控制項使用者介面的外觀,而不需要變更其內容和行為。

例如,按一下 Button 時會引發 Click 事件。 如果您變更按鈕的範本以顯示 Ellipse 圖形,會變更控制項的視覺外觀,但不會變更功能。 您還是可以按一下控制項的視覺外觀,Click 事件也會如預期般引發。

An elliptical button and a second window

資料範本

控制項範本可讓您指定控制項的外觀,而資料範本則可讓您指定控制項內容的外觀。 資料範本通常可用來增強繫結資料的顯示方式。 下圖顯示繫結至 Task 物件集合的 ListBox 預設外觀,其中每項工作都有名稱、描述和優先順序:

A list box with the default appearance

預設外觀是您可預期的 ListBox外觀。 不過,每項工作的預設外觀只包含工作名稱。 若要顯示工作名稱、描述和優先權,則必須使用 ListBox 變更 DataTemplate控制項之繫結清單項目的預設外觀。 以下範例套用了為 Task 物件建立的資料範本。

List box that uses a data template

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>

由於這種樣式是以所有 Button 控制項為目標,系統會將該樣式自動套用至視窗中的所有按鈕,如下圖所示:

Two orange buttons

如需詳細資訊,請參閱樣式和範本

資源

應用程式中的控制項應該共用相同的外觀,可包含從字型和背景色彩,到控制項範本、資料範本和樣式的任何項目。 您可以使用 WPF 對使用者介面資源的支援,將這些資源封裝到單一位置以重複使用。

下列範例會定義 ButtonLabel 共用的一般背景色彩:

<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

如需自訂控制項的詳細資訊,請參閱控制項撰寫概觀

另請參閱