教學課程:使用 .NET 建立新的 WPF 應用程式

在本簡短教學課程中,您將瞭解如何使用Visual Studio建立新的 Windows Presentation Foundation (WPF) 應用程式。 產生初始應用程式之後,您將瞭解如何新增控件,以及如何處理事件。 在本教學課程結束時,您將有一個簡單的應用程式,可將名稱新增至清單框。

重要

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

在本教學課程中,您會了解如何:

  • 建立新的 WPF 應用程式
  • 將控件新增至表單
  • 處理控制項事件以提供應用程式功能
  • 執行應用程式

以下是您將在此教學課程中建置的應用程式預覽:

Finished sample app for WPF tutorial

必要條件

提示

使用 Visual Studio 2022 17.4 版或更新版本,並安裝 .NET 7 和 .NET 6 個別元件。 Visual Studio 2022 17.4 版已新增 .NET 7 的支援。

建立 WPF 應用程式

建立新應用程式的第一個步驟是開啟Visual Studio,並從範本產生應用程式。

  1. 開啟 Visual Studio。

  2. 選取 [建立新專案]

    Create a new WPF project in Visual Studio 2022 for .NET. 6

  3. 在 [ 搜尋範本 ] 方塊中,輸入 wpf,然後按 Enter

  4. 在程式代碼語言下拉式清單中,選擇 [C#] 或 [Visual Basic]。

  5. 在範本清單中,選取 [WPF 應用程式 ],然後選取 [ 下一步]。

    重要

    請勿選取 WPF 應用程式 (.NET Framework 範本。

    下圖顯示 C# 和 Visual Basic .NET 專案範本。 如果您已套用程式 代碼語言 篩選,您會看到對應的範本。

    Search for the WPF template in Visual Studio 2022 for .NET. 6

  6. 在 [ 設定新專案 ] 視窗中,執行下列動作:

    1. 在 [項目名稱] 方塊中,輸入 [名稱]。
    2. 選取 [ 將方案與專案放在相同的目錄 ] 複選框。
    3. 或者,選擇不同的 位置 來儲存您的程序代碼。
    4. 選取下一步按鈕。

    Configure new WPF project in Visual Studio 2022 for .NET 6

  7. 在 [其他資訊] 視窗中,選取目標 Framework.NET 6.0 (長期支援)。 選取建立按鈕。

    Select target framework for new WPF project in Visual Studio 2022 for .NET 6

  1. 開啟 Visual Studio。

  2. 選取 [建立新專案]

    Create a new WPF project in Visual Studio 2022 for .NET 7.

  3. 在 [ 搜尋範本 ] 方塊中,輸入 wpf,然後按 Enter

  4. 在程式代碼語言下拉式清單中,選擇 [C#] 或 [Visual Basic]。

  5. 在範本清單中,選取 [WPF 應用程式 ],然後選取 [ 下一步]。

    重要

    請勿選取 WPF 應用程式 (.NET Framework 範本。

    下圖顯示 C# 和 Visual Basic .NET 專案範本。 如果您已套用程式 代碼語言 篩選,您會看到對應的範本。

    Search for the WPF template in Visual Studio 2022 for .NET. 7

  6. 在 [ 設定新專案 ] 視窗中,執行下列動作:

    1. 在 [項目名稱] 方塊中,輸入 [名稱]。
    2. 選取 [ 將方案與專案放在相同的目錄 ] 複選框。
    3. 或者,選擇不同的 位置 來儲存您的程序代碼。
    4. 選取下一步按鈕。

    Configure new WPF project in Visual Studio 2022 for .NET 7

  7. 在 [其他資訊] 視窗中,選取目標 Framework.NET 7.0 (標準字詞支援)。 選取建立按鈕。

    Select target framework for new WPF project in Visual Studio 2022 for .NET 7

產生應用程式之後,Visual Studio 應該開啟預設視窗 MainWindow 的 XAML 設計工具窗格。 如果看不到設計工具,請在 [方案總管] 窗格中按兩下MainWindow.xaml 檔案,以開啟設計工具。

Visual Studio 的重要部分

Visual Studio 中 WPF 的支援有五個重要元件,您會在建立應用程式時與其互動:

The important components of Visual Studio you should know when creating a WPF project for .NET

  1. 方案總管

    您的所有項目檔、程式代碼、視窗、資源都會出現在此窗格中。

  2. 屬性

    此窗格會顯示您可以根據選取的項目所設定的屬性設定。 例如,如果您從 方案總管 選取專案,您會看到與檔案相關的屬性設定。 如果您在設計師選取物件,您會看到該專案的設定。

  3. 工具箱

    工具箱包含您可以新增至表單的所有控制項。 若要將控件新增至目前窗體,請按兩下控件或拖放控件。

  4. XAML 設計工具

    這是 XAML 檔的設計工具。 它是互動式的,您可以從 [工具箱] 拖放物件。 藉由在設計工具中選取和移動專案,您可以可視化方式撰寫應用程式的使用者介面(UI)。

    當設計工具與編輯器都可見時,其中一個變更會反映在另一個中。 當您在設計工具中選取專案時,[ 屬性 ] 窗格會顯示該物件的相關屬性和屬性。

  5. XAML 程式碼編輯器

    這是 XAML 檔的 XAML 程式代碼編輯器。 XAML 程式代碼編輯器是不使用設計工具手動製作 UI 的方法。 設計工具可能會在設計工具中加入控件時推斷控件上的屬性值。 XAML 程式代碼編輯器提供您更多的控制權。

    當設計工具與編輯器都可見時,其中一個變更會反映在另一個中。 當您在程式代碼編輯器中巡覽文字插入號時,[ 屬性 ] 窗格會顯示該物件的相關屬性和屬性。

檢查 XAML

建立項目之後,會顯示 XAML 程式代碼編輯器,其中包含最少的 XAML 程式代碼以顯示視窗。 如果編輯器未開啟,請按兩下 方案總管中的MainWindow.xaml專案。 您應該會看到類似下列範例的 XAML:

<Window x:Class="Names.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:Names"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

讓我們細分此 XAML 程式代碼,以進一步瞭解它。 XAML 只是 XML,可由 WPF 使用的編譯程序處理。 它會描述 WPF UI,並與 .NET 程式代碼互動。 若要瞭解 XAML,您應該至少熟悉 XML 的基本概念。

檔根 <Window> 代表 XAML 檔案所描述的物件類型。 已宣告八個屬性,它們通常屬於三個類別:

  • 命名空間

    XML 命名空間會提供 XML 的結構,以判斷檔案中可以宣告哪些 XML 內容。

    main xmlns 屬性會匯入整個檔案的 XML 命名空間,在此情況下,會對應至 WPF 所宣告的類型。 其他 XML 命名空間會宣告前置詞,並匯入 XAML 檔案的其他類型和物件。 例如, xmlns:local 命名空間會宣告前置詞, local 並對應至專案所宣告的物件,也就是在程式代碼命名空間中宣告的物件 Names

  • x:Class 屬性

    這個屬性會將 對應 <Window> 至程式代碼所定義的類型: MainWindow.xaml.csMainWindow.xaml.vb 檔案,也就是 Names.MainWindow 類別。

  • Title 屬性

    XAML 物件上宣告的任何一般屬性會設定該物件的屬性。 在此情況下,屬性會 Title 設定 Window.Title 屬性。

變更視窗

首先,執行專案並查看預設輸出。 您會看到一個彈出視窗,其中沒有任何控制項,以及 MainWindow標題:

A blank WPF app

在我們的範例應用程式中,此視窗太大,標題列沒有描述性。 將 XAML 中的適當屬性變更為下列值,以變更視窗的標題和大小:

<Window x:Class="Names.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:Names"
        mc:Ignorable="d"
        Title="Names" Height="180" Width="260">
    <Grid>
        
    </Grid>
</Window>

準備版面配置

WPF 提供功能強大的版面配置系統,其中包含許多不同的版面配置控制件。 版面配置控制項有助於放置和調整子控件的大小,甚至可以自動進行。 在此 XAML 中提供給您的預設版面配置控制項是 <Grid> 控制項。

控件 Grid 可讓您定義數據列和數據行,就像數據表一樣,並將控件放在特定數據列和數據行組合的界限內。 您可以新增任意數目的子控件或其他版面配置控制件。Grid 例如,您可以將另一個 Grid 控件放在特定的數據列和數據行組合中,然後新的 Grid 可以定義更多數據列和數據行,並有自己的子系。

控制項 <Grid> 會定義控制項將會在其中的數據列和數據行。 網格線一律會宣告單一數據列和數據行,這表示方格預設為單一單元格。 這並沒有真正讓您在放置控件方面具有很大的彈性。

在新增數據列和數據行之前,請將新的屬性新增至 <Grid> 元素: Margin="10"。 這會從視窗內塞入網格線,使其看起來更美觀。

接下來,定義兩個數據列和兩個數據行,將方格分成四個數據格:

<Grid Margin="10">
    
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    
</Grid>

在 XAML 程式代碼編輯器或 XAML 設計工具中選取方格,您會看到 XAML 設計工具會顯示每個資料列和資料列:

A WPF app with the margin set on a grid

新增第一個控件

現在已建立方格,我們可以開始將控件新增至該方格。 首先,從標籤開始。 在 元素內建立新的<Label>專案,並在數據列和數據行定義之後,併為其指定字串值Names<Grid>

<Grid Margin="10">

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Label>Names</Label>

</Grid>

<Label>Names</Label>定義內容 Names。 有些控件會瞭解如何處理內容,有些則不會。 控件的內容會對應至 Content 屬性。 透過 XAML 屬性語法設定內容,您可以使用下列格式: <Label Content="Names" />。 這兩種方式都會完成相同的動作,將標籤的內容設定為顯示文字 Names

不過,我們有問題,標籤會佔用視窗的一半,因為它會自動指派給方格的第一個數據列和數據行。 對於第一個數據列,我們不需要那麼多的空間,因為我們只會針對標籤使用該數據列。 將 Height 第一個 <RowDefinition> 的屬性從 * 變更為 Auto。 值 Auto 會自動將網格線數據列的大小調整為其內容的大小,在此案例中為標籤控件。

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>

請注意,設計工具現在會顯示佔用少量可用高度的標籤。 現在還有更多空間可供下一列佔用。 大部分的控件都會定義某種高度和寬度值,它們應該佔用最適合它們的高度和寬度值。 例如,標籤具有高度值,可確保您可以讀取它。

A WPF app with the margin set on a grid and a label control in the first row

控件放置

讓我們來談談控件放置。 在上一節中建立的標籤會自動放在方格的第 0 列和資料行 0 中。 數據列和數據行的編號從 0 開始,並針對每個新數據列或數據行遞增 1。 控件不知道方格的任何專案,而且控制控制其在方格內的位置。 控件甚至可以放在一些其他配置控制件中,該控件有自己的規則集,定義如何放置控件。

當控件不知道方格時,如何告訴控件使用不同的數據列或數據行? 附加屬性! 網格線會利用 WPF 所提供的強大屬性系統。 方格會定義子控件可以宣告及使用的新屬性。 屬性實際上不存在於控件本身上,當控件新增至方格時,它們會由方格附加。

格線會定義兩個屬性,以判斷子控制的資料列和資料列位置: Grid.RowGrid.Column。 如果從控件省略這些屬性,則表示它們具有預設值 0,因此控件會放在方格的數據列 0 和數據行 0 中。 將 屬性設定Grid.Column1,嘗試變更 控制件的位置<Label>

<Label Grid.Column="1">Names</Label>

請注意您的標籤現在移至第二個數據行的方式。 您可以使用 Grid.RowGrid.Column 附加屬性來放置我們將建立的下一個控件。 不過,現在請將標籤還原至數據行 0。

建立名稱清單框

現在,網格線已正確調整大小並建立標籤,請在標籤下方的數據列上新增清單框控制件。 清單框會位於數據列 1 和數據列 0中。 我們也會提供此控制件的名稱 lstNames。 一旦命名控件,就可以在程序代碼後置中參考它。 名稱會指派給具有 屬性的 x:Name 控件。

<Grid Margin="10">

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Label>Names</Label>
    <ListBox Grid.Row="1" x:Name="lstNames" />

</Grid>

新增其餘控制件

我們將新增的最後兩個控件是文本框和按鈕,使用者將用來輸入名稱以新增至清單框。 不過,我們不會嘗試為方格建立更多數據列和數據行,而是將這些控件放入版面 <StackPanel> 配置控件中。

堆疊面板與方格在控件的放置方式上不同。 當您告訴方格控件要與和 Grid.Column 附加屬性在一起Grid.Row的位置時,堆棧面板會自動放置第一個控件,然後在控件之後放置下一個控件,繼續直到放置所有控件為止。 它會「堆疊」彼此下方的每個控件。

<StackPanel> 清單框之後建立控件,並將它放在方格列數據行 11中。 新增名為 Margin 且值為 5,0,0,0的另一個屬性:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label>Names</Label>
<ListBox Grid.Row="1" x:Name="lstNames" />

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    
</StackPanel>

屬性 Margin 先前在方格上使用,但我們只放入單一值 10。 現在我們已在堆疊面板上使用的值 5,0,0,0 。 邊界是類型,而且可以解譯這兩個 Thickness 值。 粗細分別定義矩形框架、左、右下、兩側的空間。 如果邊界的值是單一值,則會針對四端使用該值。

接下來,在中<StackPanel>建立 <TextBox><Button> 控件。

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    <TextBox x:Name="txtName" />
    <Button x:Name="btnAdd" Margin="0,5,0,0">Add Name</Button>
</StackPanel>

視窗的配置已完成。 不過,我們的應用程式沒有任何邏輯可實際運作。 接下來,我們需要將控件事件連結至程序代碼,並讓應用程式實際執行某些動作。

新增 Click 事件的程序代碼

<Button>我們建立的事件Click會在使用者按下按鈕時引發。 您可以訂閱此事件,並新增程式代碼以將名稱新增至清單框。 就像藉由新增 XAML 屬性在控件上設定屬性一樣,您可以使用 XAML 屬性來訂閱事件。 將 Click 屬性設定為 ButtonAddName_Click

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    <TextBox x:Name="txtName" />
    <Button x:Name="btnAdd" Margin="0,5,0,0" Click="ButtonAddName_Click">Add Name</Button>
</StackPanel>

現在您需要產生處理程式程式代碼。 以滑鼠右鍵按兩下 ButtonAddName_Click ,然後選取 [移至定義]。 此動作會在程式代碼後置中為您產生方法,其符合您輸入的處理程式名稱。

private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{

}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)

End Sub

接下來,新增下列程式代碼以執行下列三個步驟:

  1. 請確定文字框包含名稱。
  2. 驗證文字框中輸入的名稱不存在。
  3. 將名稱新增至清單框。
private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{
    if (!string.IsNullOrWhiteSpace(txtName.Text) && !lstNames.Items.Contains(txtName.Text))
    {
        lstNames.Items.Add(txtName.Text);
        txtName.Clear();
    }
}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)
    If Not String.IsNullOrWhiteSpace(txtName.Text) And Not lstNames.Items.Contains(txtName.Text) Then
        lstNames.Items.Add(txtName.Text)
        txtName.Clear()
    End If
End Sub

執行應用程式

既然事件已經編碼,您可以按 F5 鍵或從功能表中選取> [偵錯開始偵錯] 來執行應用程式。 視窗隨即顯示,您可以在文字框中輸入名稱,然後按下按鈕加以新增。

Running a Windows Presentation Foundation (WPF) for .NET app.

下一步