共用方式為


教學課程:在 Visual Studio 2019 中建立您的第一個 WPF 應用程式

本文說明如何開發 Windows Presentation Foundation (WPF) 傳統型應用程式,其中包含大多數 WPF 應用程式常見元素:Extensible Application Markup Language (XAML) 標記、程式碼後置、應用程式定義、控制項、版面配置、資料繫結和樣式。 若要開發應用程式,您將使用 Visual Studio。

重要

本文針對 .NET Framework 所撰寫。 若要開始使用 .NET 7,請參閱教學課程:建立新的 WPF 應用程式 (WPF .NET)

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

  • 建立 WPF 專案。
  • 使用 XAML 以設計應用程式的使用者介面 (UI) 外觀。
  • 撰寫程式碼以建置應用程式的行為。
  • 建立應用程式定義以管理應用程式。
  • 加入控制項和建立版面配置,以組成應用程式。
  • 為整個應用程式維持一致外觀建立樣式。
  • 將 UI 繫結至資料,同時從資料填入 UI,以及讓資料和 UI 保持同步。

在教學課程結束後,您就會建置一個獨立的 Windows 應用程式,可讓使用者檢視所選取人員的費用報表。 應用程式由數個 WPF 頁面組成,這些頁面裝載於瀏覽器樣式的視窗中。

提示

本教學課程中使用的範例程式碼適用於教學課程 WPF 應用程式範例程式碼的 Visual Basic 和 C#,。

您可以使用此頁面頂端的語言選取器,在 C# 和 Visual Basic 之間切換範例程式碼的程式碼語言。

必要條件

建立應用程式專案

第一步是建立應用程式基礎結構,包括一個應用程式定義、兩個頁面和一個影像。

  1. 在 Visual Basic 或 Visual C# 中,建立名為 ExpenseIt 的新 WPF 應用程式專案:

    1. 開啟 Visual Studio,並在 [開始] 功能表下方選取 [建立新專案]

      會開啟 [建立新專案] 對話方塊。

    2. 在 [語言] 下拉式清單中,選擇 [C#] 或 [Visual Basic]

    3. 選取 [WPF 應用程式 (.NET Framework)] 範本,然後選取 [下一步]

      Create a new project dialog[建立新專案] 對話方塊

      會開啟 [設定新專案] 對話方塊。

    4. 輸入專案名稱 ExpenseIt,然後選取 [建立]

      Configure a new project dialog[設定新專案] 對話方塊

      Visual Studio 建立專案,並為名為 MainWindow.xaml 之預設應用程式視窗開啟設計工具。

  2. 開啟 Application.xaml (Visual Basic) 或 App.xaml (C#)。

    這個 XAML 檔案定義 WPF 應用程式和任何應用程式資源。 您也應該使用此檔案指定應用程式啟動時自動顯示的 UI,在此案例中為 MainWindow.xaml

    您的 XAML 在 Visual Basic 中看起來應該如下所示:

    <Application x:Class="Application"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="MainWindow.xaml">
        <Application.Resources>
            
        </Application.Resources>
    </Application>
    

    並在 C# 中如下所示:

    <Application x:Class="ExpenseIt.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
        <Application.Resources>
             
        </Application.Resources>
    </Application>
    
  3. 開啟 MainWindow.xaml

    這個 XAML 檔案是您應用程式的主視窗,可在分頁顯示建立的內容。 Window 類別會定義視窗的屬性,例如標題、大小或圖示,並處理例如關閉或隱藏等事件。

  4. Window 元素變更為 NavigationWindow,如下列 XAML 中所示:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         ...
    </NavigationWindow>
    

    這個應用程式會根據使用者的輸入瀏覽至不同的內容。 這就是為什麼主要 Window 需要變更為 NavigationWindowNavigationWindow 會繼承 Window 的所有屬性。 XAML 檔案中的 NavigationWindow 元素會建立 NavigationWindow 類別的執行個體。 如需詳細資訊,請參閱瀏覽概觀

  5. NavigationWindow 標籤之間移除 Grid 元素。

  6. 變更 NavigationWindow 元素的 XAML 程式碼中下列屬性:

    • Title 屬性設定為 「ExpenseIt」。

    • Height 屬性設定為 350 像素。

    • Width 屬性設定為 500 像素。

    您的 XAML 看起來應該與下列 Visual Basic 範例相同:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
     
    </NavigationWindow>
    

    並且與下列 C# 範例相同:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
        
    </NavigationWindow>
    
  7. 開啟 MainWindow.xaml.vbMainWindow.xaml.cs

    這個檔案是程式碼後置檔案,其中包含的程式碼可處理 MainWindow.xaml 中所宣告的事件。 這個檔案包含 XAML 中定義之視窗的部分類別。

  8. 如果您正在使用 C#,將類別 MainWindow 變更為 NavigationWindow 的衍生。 (在 Visual Basic 中,當您在 XAML 中變更視窗時會自動發生。)您的 C# 程式碼外觀現在應該如下圖所示:

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : NavigationWindow
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    }
    

將檔案新增至應用程式

在本節中,您要在應用程式中加入兩頁網頁和一個影像。

  1. 將新頁面新增至專案,並將其命名為 ExpenseItHome.xaml

    1. 在 [方案總管] 中,以滑鼠右鍵按一下 ExpenseIt 專案節點,然後選擇 [新增] > [新資料夾]

    2. 在 [新增專案] 對話方塊中,頁面 (WPF) 範本已選取。 輸入名稱 ExpenseItHome,然後選取 [新增]

    這個頁面是應用程式啟動時顯示的第一個頁面。 它會顯示一份使用者可從中選取的人員清單,以供其查看費用報表。

  2. 開啟 [ExpenseItHome.xaml]。

  3. Title 設定為「ExpenseIt - Home」。

  4. DesignHeight 設為 350 像素,並將 DesignWidth 設為 500 像素。

    現在會顯示 XAML,如下方 Visual Basic 所示:

    <Page x:Class="ExpenseItHome"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="350" d:DesignWidth="500"
      Title="ExpenseIt - Home">
        <Grid>
            
        </Grid>
    </Page>
    

    並且與下列 C# 範例相同:

    <Page x:Class="ExpenseIt.ExpenseItHome"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - Home">
    
        <Grid>
            
        </Grid>
    </Page>
    
  5. 開啟 MainWindow.xaml

  6. Source 屬性新增至 NavigationWindow 元素,並將其設定為「ExpenseItHome.xaml」。

    這會將 ExpenseItHome.xaml 設成應用程式啟動時開啟的第一個頁面。

    Visual Basic 中的 XAML 範例:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    以及在 C# 中:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    提示

    您也可以設定 [屬性] 視窗 [其他] 類別中的資源屬性。

    Source property in Properties window[屬性] 視窗中的資源屬性

  7. 將另一個新的 WPF 頁面新增至專案,並將其命名為 ExpenseReportPage.xaml:

    1. 在 [方案總管] 中,以滑鼠右鍵按一下 ExpenseIt 專案節點,然後選擇 [新增] > [新資料夾]

    2. 在 [新增元素] 對話方塊中,選取 [頁面 (WPF)]。 輸入 ExpenseReportPage 名稱,然後選取 [新增]

    這個頁面會顯示 ExpenseItHome 頁面中所選取之人員的費用報表。

  8. 開啟 ExpenseReportPage.xaml

  9. Title 設定為「ExpenseIt - Home」。

  10. DesignHeight 設為 350 像素,並將 DesignWidth 設為 500 像素。

    ExpenseReportPage.xaml 現在在 Visual Basic 中如下所示:

    <Page x:Class="ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
          Title="ExpenseIt - View Expense">
        <Grid>
            
        </Grid>
    </Page>
    

    並在 C# 中如下所示:

    <Page x:Class="ExpenseIt.ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - View Expense">
    
        <Grid>
            
        </Grid>
    </Page>
    
  11. 開啟 ExpenseItHome.xaml.vbExpenseReportPage.xaml.vb,或是 ExpenseItHome.xaml.cs ExpenseReportPage.xaml.cs

    當您建立新的頁面檔案時,Visual Studio 會自動建立程式碼後置檔案。 這些程式碼後置檔案會處理用於回應使用者輸入的邏輯。

    您的程式碼應該看起來與下列 ExpenseItHome 範例相同:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseItHome.xaml
        /// </summary>
        public partial class ExpenseItHome : Page
        {
            public ExpenseItHome()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseItHome
    
    End Class
    

    與下列 ExpenseReportPage 範例相同:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseReportPage.xaml
        /// </summary>
        public partial class ExpenseReportPage : Page
        {
            public ExpenseReportPage()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseReportPage
    
    End Class
    
  12. 將名為 watermark.png 的影像加入至專案。 您可以建立自己的影像、從範例程式碼複製檔案,或從 microsoft/WPF-Samples GitHub 存放庫取得檔案。

    1. 以滑鼠右鍵按一下專案節點,然後選取 [新增] > [現有元素],然後按一下 [Shift+Alt+A]

    2. 在 [新增現有元素] 對話方塊中,將檔案篩選設定為 [所有檔案] 或 [影像檔案],瀏覽至要使用的影像檔案,然後選取 [新增]

    3. 在 [方案總管] 中選取影像檔案,然後在 [屬性] 視窗中,將 [建置動作] 設定為 [資源]

建置並執行應用程式

  1. 若要建置和執行應用程式,按 F5 或選取 [偵錯]功能表的 [開始偵錯]

    下圖顯示具有 NavigationWindow 按鈕的應用程式:

    Application after you build and run it.建置並執行後的應用程式。

  2. 關閉應用程式以返回 Visual Studio。

建立配置

版面配置會按照順序放置 UI 元素,也會在重新調整 UI 大小時管理這些元素的大小和位置。 您通常會建立具有下列其中一個版面配置控制項的版面配置:

  • Canvas - 使用區域的相對座標,定義可以明確定位子元素位置的 Canvas 區域。
  • DockPanel - 定義可以水平或垂直 (相對於其他子元素) 排列子元素的區域。
  • Grid - 定義彈性的格線區域,由欄與列組成。
  • StackPanel - 將子元素排成單一行,以水平或垂直方式排列。
  • VirtualizingStackPanel - 排列和虛擬化單一水平或垂直行的內容。
  • WrapPanel - 將子元素置放於由左至右的連續位置,其中會在包含方塊的邊緣將內容換至下一行。 後續順序會依序由上而下或由左而右,需視方向屬性的值而定。

這些版面配置控制項都支援其子元素的特殊版面配置類型。 ExpenseIt 頁面可以調整大小,而且每個頁面都有元素會沿著其他元素水平和垂直排列。 在此範例中,Grid 用於應用程式的版面配置元素。

提示

如需 Panel 元素的詳細資訊,請參閱面板概觀。 如需版面配置的詳細資訊,請參閱 版面配置

在本節中,您會將欄和列定義加入至 ExpenseItHome.xaml 中的 Grid,以建立含有一欄三列、邊界為 10 個像素的表格。

  1. ExpenseItHome.xaml 中,將 Grid 元素上的 Margin 屬性設定為 「10,0,10,10」,其對應至左邊、上方、右邊和下方邊界:

    <Grid Margin="10,0,10,10">
    

    提示

    您也可以在 [屬性] 視窗中的 [版面配置] 類別下方設定 [邊界] 值:

    Margin values in Properties window屬性視窗中的 [邊界] 值

  2. Grid 標籤中加入下列 XAML 程式碼,以建立資料列和資料行定義:

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    

    兩個資料列的 Height 會設定為 Auto,這表示資料列會根據其中內容來調整資料列大小。 預設 HeightStar 的調整大小,這表示資料列高度是可用空間的加權比例。 例如,如果有兩列的高度都是「*」的Height,則每列的高度會各佔可用空間的一半。

    您的 Grid 現在應該會包含下列 XAML:

    <Grid Margin="10,0,10,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
    </Grid>
    

新增控制項

在本節中,您將更新首頁 UI 以顯示人員清單,並在其中選取人員來顯示其費用報表。 控制項是可讓使用者與您應用程式互動的 UI 物件。 如需詳細資訊,請參閱 控制項

若要建立此 UI,請將下列元素新增至 ExpenseItHome.xaml

  • ListBox (適用於人員清單)。
  • Label (適用於清單標頭)。
  • Button (用來按一下即可檢視清單中選取之人員的費用報表)。

每個控制項都會藉由設定 Grid.Row 附加屬性,放置在 Grid 的一個資料列中。 如需附加屬性的詳細資訊,請參閱 附加屬性概觀

  1. ExpenseItHome.xamlGrid 標籤之間加入下列 XAML:

    
    <!-- People list -->
    <Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4">
        <Label VerticalAlignment="Center" Foreground="White">Names</Label>
    </Border>
    <ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1">
        <ListBoxItem>Mike</ListBoxItem>
        <ListBoxItem>Lisa</ListBoxItem>
        <ListBoxItem>John</ListBoxItem>
        <ListBoxItem>Mary</ListBoxItem>
    </ListBox>
    
    <!-- View report button -->
    <Button Grid.Column="0" Grid.Row="2" Margin="0,10,0,10" Width="125" Height="25" HorizontalAlignment="Right">View</Button>
    

    提示

    您也可以將控制項從 [工具箱] 視窗拖放至 [設計] 視窗,然後在 [屬性] 視窗中設定其屬性,以這種方式建立控制項。

  2. 建置並執行應用程式。

    下圖顯示影像您建立的控制項:

ExpenseIt sample screenshot displaying a list of namesExpenseIt 範例螢幕擷取畫面,其中顯示名稱清單

新增影像和標題

在本節中,您會使用影像和網頁標題更新首頁 UI。

  1. ExpenseItHome.xaml 中,將另一個資料行新增至具有固定 Width 230 像素的 ColumnDefinitions

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="230" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    
  2. 將另一個資料列新增至 RowDefinitions,總共會有四個資料列:

    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
  3. 將三個控制項中的 Grid.Column 屬性設定為 1,將控制項移動至第二個資料行 (Border、ListBox 和 Button)。

  4. 將每一個控制項的 Grid.Row 值遞增為 1,以將每個控制項遞減一個資料列 (Border、ListBox 和 Button) 以及 Border 元素。

    三個控制項的 XAML 現在如下列所示:

      <Border Grid.Column="1" Grid.Row="1" Height="35" Padding="5" Background="#4E87D4">
          <Label VerticalAlignment="Center" Foreground="White">Names</Label>
      </Border>
      <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
          <ListBoxItem>Mike</ListBoxItem>
          <ListBoxItem>Lisa</ListBoxItem>
          <ListBoxItem>John</ListBoxItem>
          <ListBoxItem>Mary</ListBoxItem>
      </ListBox>
    
      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right">View</Button>
    
  5. Background 屬性設定為 watermark.png 影像檔,方法是在 <Grid></Grid> 標籤之間新增下列 XAML:

    <Grid.Background>
        <ImageBrush ImageSource="watermark.png"/>
    </Grid.Background>
    
  6. Border 元素之前,新增具有「檢視費用報表」內容的 Label。 此標籤是頁面標題。

    <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
            FontWeight="Bold" FontSize="18" Foreground="#0066cc">
        View Expense Report
    </Label>
    
  7. 建置並執行應用程式。

下圖顯示您剛新增的應用程式結果

ExpenseIt sample screenshot showing the new image background and page titleExpenseIt 範例螢幕擷取畫面,其中顯示新的影像背景和網頁標題

加入程式碼以處理事件

  1. ExpenseItHome.xaml 中,新增 Click 事件處理常式至 Button 元素。 如需詳細資訊,請參閱操作說明:建立簡單的事件處理常式

      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right" Click="Button_Click">View</Button>
    
  2. 開啟 ExpenseItHome.xaml.vbExpenseItHome.xaml.cs

  3. 將下列點擊按鈕事件處理常式程式碼新增至 ExpenseItHome 類別。 事件處理常式會開啟 ExpenseReportPage 頁面。

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage();
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage()
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

建立 ExpenseReportPage 的 UI

ExpenseReportPage.xaml 會顯示在 ExpenseItHome 頁面上選取之人員的費用報表。 在本節中,您將建立 ExpenseReportPage 的 UI。 您會將背景和填滿色彩加入至各個 UI 元素。

  1. 開啟 ExpenseReportPage.xaml

  2. Grid 標籤之間加入下列 XAML:

     <Grid.Background>
         <ImageBrush ImageSource="watermark.png" />
     </Grid.Background>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="230" />
         <ColumnDefinition />
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition />
     </Grid.RowDefinitions>
    
    
     <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
     FontWeight="Bold" FontSize="18" Foreground="#0066cc">
         Expense Report For:
     </Label>
     <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
         <Grid.ColumnDefinitions>
             <ColumnDefinition />
             <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto" />
             <RowDefinition Height="Auto" />
             <RowDefinition />
         </Grid.RowDefinitions>
    
         <!-- Name -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Name:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <!-- Department -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Department:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
               HorizontalAlignment="Left">
             <!-- Expense type and Amount table -->
             <DataGrid  AutoGenerateColumns="False" RowHeaderWidth="0" >
                 <DataGrid.ColumnHeaderStyle>
                     <Style TargetType="{x:Type DataGridColumnHeader}">
                         <Setter Property="Height" Value="35" />
                         <Setter Property="Padding" Value="5" />
                         <Setter Property="Background" Value="#4E87D4" />
                         <Setter Property="Foreground" Value="White" />
                     </Style>
                 </DataGrid.ColumnHeaderStyle>
                 <DataGrid.Columns>
                     <DataGridTextColumn Header="ExpenseType" />
                     <DataGridTextColumn Header="Amount"  />
                 </DataGrid.Columns>
             </DataGrid>
         </Grid>
     </Grid>
    

    此UI與 ExpenseItHome.xaml 類似,但報表資料會顯示在 DataGrid

  3. 建置並執行應用程式。

  4. 選取 [檢視] 按鈕。

    報表頁面隨即出現。 請注意,返回導覽按鈕已啟用。

下圖顯示加入至 ExpenseReportPage.xaml 的 UI 元素。

ExpenseIt sample screenshot showing the UI just created for the ExpenseReportPage.ExpenseIt 範例螢幕擷取畫面,其中顯示剛為 ExpenseReportPage 建立的 UI。

樣式控制項

在 UI 中有各種元素,其中所有同類型的元素外觀通常一樣。 UI 使用 樣式,使多個元素可重複使用外觀。 樣式的重複使用性有助於簡化 XAML 的建立和管理。 本節會將先前步驟中定義的個別元素屬性 (Attribute) 取代為樣式。

  1. 開啟 Application.xaml App.xaml

  2. Grid 標籤之間加入下列 XAML:

    
    <!-- Header text style -->
    <Style x:Key="headerTextStyle">
        <Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
        <Setter Property="Label.FontWeight" Value="Bold"></Setter>
        <Setter Property="Label.FontSize" Value="18"></Setter>
        <Setter Property="Label.Foreground" Value="#0066cc"></Setter>
    </Style>
    
    <!-- Label style -->
    <Style x:Key="labelStyle" TargetType="{x:Type Label}">
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Margin" Value="0,0,0,5" />
    </Style>
    
    <!-- DataGrid header style -->
    <Style x:Key="columnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
        <Setter Property="Foreground" Value="White" />
    </Style>
    
    <!-- List header style -->
    <Style x:Key="listHeaderStyle" TargetType="{x:Type Border}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
    </Style>
    
    <!-- List header text style -->
    <Style x:Key="listHeaderTextStyle" TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="White" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="HorizontalAlignment" Value="Left" />
    </Style>
    
    <!-- Button style -->
    <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
        <Setter Property="Width" Value="125" />
        <Setter Property="Height" Value="25" />
        <Setter Property="Margin" Value="0,10,0,0" />
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
    

    這個 XAML 會加入下列樣式:

    • headerTextStyle:格式化頁面標題 Label

    • labelStyle:格式化 Label 控制項。

    • columnHeaderStyle:格式化 DataGridColumnHeader

    • listHeaderStyle:格式化清單標頭 Border 控制項。

    • listHeaderTextStyle:格式化清單標頭Label

    • buttonStyle:在 ExpenseItHome.xaml 上格式化 Button

    請注意,樣式是 Application.Resources 屬性元素的資源和子系。 在這裡,樣式會套用至應用程式中的所有元素。 如需在 .NET 應用程式中使用資源的範例,請參閱使用應用程式資源

  3. 開啟 ExpenseItHome.xaml,並以下列 XAML 取代 Grid 元素之間的所有內容:

       <Grid.Background>
           <ImageBrush ImageSource="watermark.png"  />
       </Grid.Background>
      
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="230" />
           <ColumnDefinition />
       </Grid.ColumnDefinitions>
       
       <Grid.RowDefinitions>
           <RowDefinition/>
           <RowDefinition Height="Auto"/>
           <RowDefinition />
           <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
    
       <!-- People list -->
      
       <Label Grid.Column="1" Style="{StaticResource headerTextStyle}" >
           View Expense Report
       </Label>
       
       <Border Grid.Column="1" Grid.Row="1" Style="{StaticResource listHeaderStyle}">
           <Label Style="{StaticResource listHeaderTextStyle}">Names</Label>
       </Border>
       <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
           <ListBoxItem>Mike</ListBoxItem>
           <ListBoxItem>Lisa</ListBoxItem>
           <ListBoxItem>John</ListBoxItem>
           <ListBoxItem>Mary</ListBoxItem>
       </ListBox>
    
       <!-- View report button -->
       <Button Grid.Column="1" Grid.Row="3" Click="Button_Click" Style="{StaticResource buttonStyle}">View</Button>
    

    套用樣式會移除並取代諸如 VerticalAlignmentFontFamily 這類會定義每個控制項外觀的屬性。 例如,headerTextStyle 會套用至「檢視費用報表」Label

  4. 開啟 ExpenseReportPage.xaml

  5. 使用下列 XAML 開啟 Grid 元素之間的所有內容:

      <Grid.Background>
          <ImageBrush ImageSource="watermark.png" />
      </Grid.Background>
      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
      </Grid.RowDefinitions>
    
    
      <Label Grid.Column="1" Style="{StaticResource headerTextStyle}">
          Expense Report For:
      </Label>
      <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition Height="Auto" />
              <RowDefinition />
          </Grid.RowDefinitions>
    
          <!-- Name -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Name:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <!-- Department -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" 
      Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Department:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
                HorizontalAlignment="Left">
              <!-- Expense type and Amount table -->
              <DataGrid ColumnHeaderStyle="{StaticResource columnHeaderStyle}" 
                        AutoGenerateColumns="False" RowHeaderWidth="0" >
                  <DataGrid.Columns>
                      <DataGridTextColumn Header="ExpenseType" />
                      <DataGridTextColumn Header="Amount"  />
                  </DataGrid.Columns>
              </DataGrid>
          </Grid>
      </Grid>
    

    這樣會將 XAML 加入 LabelBorder 元素。

  6. 建置並執行應用程式。 視窗外觀與先前相同。

    ExpenseIt sample screenshot with the same appearance as in the last section.ExpenseIt 範例螢幕擷取畫面,其外觀與上一節相同。

  7. 關閉應用程式以返回 Visual Studio。

將資料繫結到控制項

在本節中,您會建立繫結至各個控制項的 XML 資料。

  1. ExpenseItHome.xaml 中,開啟 Grid 元素之後,新增下列 XAML 來建立包含每個人員資料的 XmlDataProvider

    <Grid.Resources>
        <!-- Expense Report Data -->
        <XmlDataProvider x:Key="ExpenseDataSource" XPath="Expenses">
            <x:XData>
                <Expenses xmlns="">
                    <Person Name="Mike" Department="Legal">
                        <Expense ExpenseType="Lunch" ExpenseAmount="50" />
                        <Expense ExpenseType="Transportation" ExpenseAmount="50" />
                    </Person>
                    <Person Name="Lisa" Department="Marketing">
                        <Expense ExpenseType="Document printing"
              ExpenseAmount="50"/>
                        <Expense ExpenseType="Gift" ExpenseAmount="125" />
                    </Person>
                    <Person Name="John" Department="Engineering">
                        <Expense ExpenseType="Magazine subscription" 
             ExpenseAmount="50"/>
                        <Expense ExpenseType="New machine" ExpenseAmount="600" />
                        <Expense ExpenseType="Software" ExpenseAmount="500" />
                    </Person>
                    <Person Name="Mary" Department="Finance">
                        <Expense ExpenseType="Dinner" ExpenseAmount="100" />
                    </Person>
                </Expenses>
            </x:XData>
        </XmlDataProvider>
    </Grid.Resources>
    

    資料會建立為 Grid 資源。 此資料通常會載入為檔案,但為求簡化會內嵌資料。

  2. <Grid.Resources> 元素內,新增下列 <xref:System.Windows.DataTemplate> 元素,其定義如何在 <XmlDataProvider> 元素之後,於 ListBox 中顯示資料:

    <Grid.Resources>
        <!-- Name item template -->
        <DataTemplate x:Key="nameItemTemplate">
            <Label Content="{Binding XPath=@Name}"/>
        </DataTemplate>
    </Grid.Resources>
    

    如需資料範本的詳細資訊,請參閱資料範本化概觀

  3. 將現有的 ListBox 取代為下列 XAML:

    <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2" 
             ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}"
             ItemTemplate="{StaticResource nameItemTemplate}">
    </ListBox>
    

    這個 XAML 會將 ItemsSourceListBox 屬性繫結到資料來源,並套用資料範本作為 ItemTemplate

將資料連接至控制項

接下來,您將新增程式碼來擷取在 ExpenseItHome 頁面上選取的名稱,並將其傳遞至 ExpenseReportPage 的建構函式。 ExpenseReportPage 會以傳遞的元素設定其資料內容,而這就是 ExpenseReportPage.xaml 中定義的控制項繫結的元素。

  1. 開啟 ExpenseReportPage.xaml.vbExpenseReportPage.xaml.cs

  2. 加入一個可接受物件的建構函式,如此您就可以傳遞選取之人員的費用報表資料。

    public partial class ExpenseReportPage : Page
    {
        public ExpenseReportPage()
        {
            InitializeComponent();
        }
    
        // Custom constructor to pass expense report data
        public ExpenseReportPage(object data):this()
        {
            // Bind to expense report data.
            this.DataContext = data;
        }
    }
    
    Partial Public Class ExpenseReportPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    
        ' Custom constructor to pass expense report data
        Public Sub New(ByVal data As Object)
            Me.New()
            ' Bind to expense report data.
            Me.DataContext = data
        End Sub
    
    End Class
    
  3. 開啟 ExpenseItHome.xaml.vbExpenseItHome.xaml.cs

  4. 變更 Click 事件處理常式,以呼叫會傳遞所選人員之費用報表資料的新建構函式。

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage(this.peopleListBox.SelectedItem);
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage(Me.peopleListBox.SelectedItem)
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

使用資料範本的樣式資料

在本節中,您會使用資料範本更新資料繫結清單中每個元素的 UI。

  1. 開啟 ExpenseReportPage.xaml

  2. 將「Name」和「Department」這兩個 Label 元素的內容繫結至適當的資料來源屬性。 如需資料繫結的詳細資訊,請參閱資料繫結概觀

    <!-- Name -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Name:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Name}"></Label>
    </StackPanel>
    
    <!-- Department -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Department:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Department}"></Label>
    </StackPanel>
    
  3. 在開頭的 Grid 元素後,加入下列資料範本,定義顯示費用報表資料的方式:

    <!--Templates to display expense report data-->
    <Grid.Resources>
        <!-- Reason item template -->
        <DataTemplate x:Key="typeItemTemplate">
            <Label Content="{Binding XPath=@ExpenseType}"/>
        </DataTemplate>
        <!-- Amount item template -->
        <DataTemplate x:Key="amountItemTemplate">
            <Label Content="{Binding XPath=@ExpenseAmount}"/>
        </DataTemplate>
    </Grid.Resources>
    
  4. DataGridTextColumn 元素取代為 DataGrid 元素下的 DataGridTemplateColumn ,並將範本套用至這些元素。 此外,請在 DataGrid 元素中指定 ItemsSource 屬性的值。

    <!-- Expense type and Amount table -->
    <DataGrid ItemsSource="{Binding XPath=Expense}" ColumnHeaderStyle="{StaticResource columnHeaderStyle}" AutoGenerateColumns="False" RowHeaderWidth="0" >
       
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="ExpenseType" CellTemplate="{StaticResource typeItemTemplate}" />
            <DataGridTemplateColumn Header="Amount" CellTemplate="{StaticResource amountItemTemplate}" />
        </DataGrid.Columns>
        
    </DataGrid>
    
  5. 建置並執行應用程式。

  6. 選取人員然後按一下 [檢視] 按鈕。

下圖顯示套用了控制項、配置、樣式、資料繫結和資料範本的 ExpenseIt 應用程式的兩頁頁面:

Both pages of the app showing the names list and an expense report.應用程式的兩頁頁面都會顯示名稱清單和費用報表。

注意

此範例展示 WPF 的特定功能,且不會遵循安全性、當地語系化和輔助功能等所有最佳做法。 如需 WPF 和 .NET 應用程式開發最佳做法的完整內容,請參閱下列主題:

下一步

在本逐步解說中,您已了解一些使用 Windows Presentation Foundation (WPF) 建立 UI 的技術。 您現在應該對資料繫結 .NET 應用程式的建置組塊有基本的了解。 如需 WPF 架構和程式設計模型的詳細資訊,請參閱下列主題:

如需建立應用程式的詳細資訊,請參閱下列主題:

另請參閱