教學課程:在 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 之間切換範例程式碼的程式碼語言。
必要條件
已安裝 .NET 桌面開發工作負載的 Visual Studio 2019。
如需安裝最新版本 Visual Studio 的詳細資訊,請參閱安裝 Visual Studio。
建立應用程式專案
第一步是建立應用程式基礎結構,包括一個應用程式定義、兩個頁面和一個影像。
在 Visual Basic 或 Visual C# 中,建立名為
ExpenseIt
的新 WPF 應用程式專案:開啟 Visual Studio,並在 [開始] 功能表下方選取 [建立新專案]。
會開啟 [建立新專案] 對話方塊。
在 [語言] 下拉式清單中,選擇 [C#] 或 [Visual Basic]。
選取 [WPF 應用程式 (.NET Framework)] 範本,然後選取 [下一步]。
會開啟 [設定新專案] 對話方塊。
輸入專案名稱
ExpenseIt
,然後選取 [建立]。Visual Studio 建立專案,並為名為 MainWindow.xaml 之預設應用程式視窗開啟設計工具。
開啟 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>
開啟 MainWindow.xaml。
這個 XAML 檔案是您應用程式的主視窗,可在分頁顯示建立的內容。 Window 類別會定義視窗的屬性,例如標題、大小或圖示,並處理例如關閉或隱藏等事件。
將 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 需要變更為 NavigationWindow。 NavigationWindow 會繼承 Window 的所有屬性。 XAML 檔案中的 NavigationWindow 元素會建立 NavigationWindow 類別的執行個體。 如需詳細資訊,請參閱瀏覽概觀。
從 NavigationWindow 標籤之間移除 Grid 元素。
變更 NavigationWindow 元素的 XAML 程式碼中下列屬性:
您的 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>
開啟 MainWindow.xaml.vb 或 MainWindow.xaml.cs。
這個檔案是程式碼後置檔案,其中包含的程式碼可處理 MainWindow.xaml 中所宣告的事件。 這個檔案包含 XAML 中定義之視窗的部分類別。
如果您正在使用 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(); } } }
將檔案新增至應用程式
在本節中,您要在應用程式中加入兩頁網頁和一個影像。
將新頁面新增至專案,並將其命名為
ExpenseItHome.xaml
:在 [方案總管] 中,以滑鼠右鍵按一下
ExpenseIt
專案節點,然後選擇 [新增] > [新資料夾]。在 [新增專案] 對話方塊中,頁面 (WPF) 範本已選取。 輸入名稱
ExpenseItHome
,然後選取 [新增]。
這個頁面是應用程式啟動時顯示的第一個頁面。 它會顯示一份使用者可從中選取的人員清單,以供其查看費用報表。
開啟 [
ExpenseItHome.xaml
]。將 Title 設定為「
ExpenseIt - Home
」。將
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>
開啟 MainWindow.xaml。
將 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>
提示
您也可以設定 [屬性] 視窗 [其他] 類別中的資源屬性。
將另一個新的 WPF 頁面新增至專案,並將其命名為 ExpenseReportPage.xaml:
在 [方案總管] 中,以滑鼠右鍵按一下
ExpenseIt
專案節點,然後選擇 [新增] > [新資料夾]。在 [新增元素] 對話方塊中,選取 [頁面 (WPF)]。 輸入 ExpenseReportPage 名稱,然後選取 [新增]。
這個頁面會顯示
ExpenseItHome
頁面中所選取之人員的費用報表。開啟 ExpenseReportPage.xaml。
將 Title 設定為「
ExpenseIt - View Expense
」。將
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>
開啟 ExpenseItHome.xaml.vb 和 ExpenseReportPage.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
將名為 watermark.png 的影像加入至專案。 您可以建立自己的影像、從範例程式碼複製檔案,或從 microsoft/WPF-Samples GitHub 存放庫取得檔案。
以滑鼠右鍵按一下專案節點,然後選取 [新增] > [現有元素],然後按一下 [Shift+Alt+A]。
在 [新增現有元素] 對話方塊中,將檔案篩選設定為 [所有檔案] 或 [影像檔案],瀏覽至要使用的影像檔案,然後選取 [新增]。
在 [方案總管] 中選取影像檔案,然後在 [屬性] 視窗中,將 [建置動作] 設定為 [資源]。
建置並執行應用程式
若要建置和執行應用程式,按 F5 或選取 [偵錯] 功能表的 [開始偵錯]。
下圖顯示具有 NavigationWindow 按鈕的應用程式:
關閉應用程式以返回 Visual Studio。
建立配置
版面配置會按照順序放置 UI 元素,也會在重新調整 UI 大小時管理這些元素的大小和位置。 您通常會建立具有下列其中一個版面配置控制項的版面配置:
- Canvas - 使用區域的相對座標,定義可以明確定位子元素位置的 Canvas 區域。
- DockPanel - 定義可以水平或垂直 (相對於其他子元素) 排列子元素的區域。
- Grid - 定義彈性的格線區域,由欄與列組成。
- StackPanel - 將子元素排成單一行,以水平或垂直方式排列。
- VirtualizingStackPanel - 排列和虛擬化單一水平或垂直行的內容。
- WrapPanel - 將子元素置放於由左至右的連續位置,其中會在包含方塊的邊緣將內容換至下一行。 後續順序會依序由上而下或由左而右,需視方向屬性的值而定。
這些版面配置控制項都支援其子元素的特殊版面配置類型。 ExpenseIt
頁面可以調整大小,而且每個頁面都有元素會沿著其他元素水平和垂直排列。 在此範例中,Grid 用於應用程式的版面配置元素。
在本節中,您會將欄和列定義加入至 ExpenseItHome.xaml
中的 Grid,以建立含有一欄三列、邊界為 10 個像素的表格。
在
ExpenseItHome.xaml
中,將 Grid 元素上的 Margin 屬性設定為 「10,0,10,10」,其對應至左邊、上方、右邊和下方邊界:<Grid Margin="10,0,10,10">
提示
您也可以在 [屬性] 視窗中的 [版面配置] 類別下方設定 [邊界] 值:
在 Grid 標籤中加入下列 XAML 程式碼,以建立資料列和資料行定義:
<Grid.ColumnDefinitions> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>
兩個資料列的 Height 會設定為 Auto,這表示資料列會根據其中內容來調整資料列大小。 預設 Height 是 Star 的調整大小,這表示資料列高度是可用空間的加權比例。 例如,如果有兩列的高度都是「*」的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
:
每個控制項都會藉由設定 Grid.Row 附加屬性,放置在 Grid 的一個資料列中。 如需附加屬性的詳細資訊,請參閱 附加屬性概觀。
在
ExpenseItHome.xaml
的 Grid 標籤之間加入下列 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>
提示
您也可以將控制項從 [工具箱] 視窗拖放至 [設計] 視窗,然後在 [屬性] 視窗中設定其屬性,以這種方式建立控制項。
建置並執行應用程式。
下圖顯示影像您建立的控制項:
新增影像和標題
在本節中,您會使用影像和網頁標題更新首頁 UI。
在
ExpenseItHome.xaml
中,將另一個資料行新增至具有固定 Width 230 像素的 ColumnDefinitions:<Grid.ColumnDefinitions> <ColumnDefinition Width="230" /> <ColumnDefinition /> </Grid.ColumnDefinitions>
將另一個資料列新增至 RowDefinitions,總共會有四個資料列:
<Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>
將三個控制項中的 Grid.Column 屬性設定為 1,將控制項移動至第二個資料行 (Border、ListBox 和 Button)。
將每一個控制項的 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>
將 Background 屬性設定為 watermark.png 影像檔,方法是在
<Grid>
和</Grid>
標籤之間新增下列 XAML:<Grid.Background> <ImageBrush ImageSource="watermark.png"/> </Grid.Background>
在 Border 元素之前,新增具有「檢視費用報表」內容的 Label。 此標籤是頁面標題。
<Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" FontWeight="Bold" FontSize="18" Foreground="#0066cc"> View Expense Report </Label>
建置並執行應用程式。
下圖顯示您剛新增的應用程式結果
加入程式碼以處理事件
在
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>
開啟
ExpenseItHome.xaml.vb
或ExpenseItHome.xaml.cs
。將下列點擊按鈕事件處理常式程式碼新增至
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 元素。
開啟 ExpenseReportPage.xaml。
在 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。建置並執行應用程式。
選取 [檢視] 按鈕。
報表頁面隨即出現。 請注意,返回導覽按鈕已啟用。
下圖顯示加入至 ExpenseReportPage.xaml 的 UI 元素。
樣式控制項
在 UI 中有各種元素,其中所有同類型的元素外觀通常一樣。 UI 使用 樣式,使多個元素可重複使用外觀。 樣式的重複使用性有助於簡化 XAML 的建立和管理。 本節會將先前步驟中定義的個別元素屬性 (Attribute) 取代為樣式。
開啟 Application.xaml 或 App.xaml。
在 Application.Resources 標籤之間加入下列 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 應用程式中使用資源的範例,請參閱使用應用程式資源。
開啟
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>
套用樣式會移除並取代諸如 VerticalAlignment 和 FontFamily 這類會定義每個控制項外觀的屬性。 例如,
headerTextStyle
會套用至「檢視費用報表」Label。開啟 ExpenseReportPage.xaml。
使用下列 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>
建置並執行應用程式。 視窗外觀與先前相同。
關閉應用程式以返回 Visual Studio。
將資料繫結到控制項
在本節中,您會建立繫結至各個控制項的 XML 資料。
在
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 資源。 此資料通常會載入為檔案,但為求簡化會內嵌資料。
在
<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>
如需資料範本的詳細資訊,請參閱資料範本化概觀。
將現有的 ListBox 取代為下列 XAML:
<ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}" ItemTemplate="{StaticResource nameItemTemplate}"> </ListBox>
這個 XAML 會將 ItemsSource 的 ListBox 屬性繫結到資料來源,並套用資料範本作為 ItemTemplate。
將資料連接至控制項
接下來,您將新增程式碼來擷取在 ExpenseItHome
頁面上選取的名稱,並將其傳遞至 ExpenseReportPage 的建構函式。 ExpenseReportPage 會以傳遞的元素設定其資料內容,而這就是 ExpenseReportPage.xaml 中定義的控制項繫結的元素。
開啟 ExpenseReportPage.xaml.vb 或 ExpenseReportPage.xaml.cs。
加入一個可接受物件的建構函式,如此您就可以傳遞選取之人員的費用報表資料。
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
開啟
ExpenseItHome.xaml.vb
或ExpenseItHome.xaml.cs
。變更 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。
開啟 ExpenseReportPage.xaml。
將「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>
在開頭的 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>
將 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>
建置並執行應用程式。
選取人員然後按一下 [檢視] 按鈕。
下圖顯示套用了控制項、配置、樣式、資料繫結和資料範本的 ExpenseIt
應用程式的兩頁頁面:
注意
此範例展示 WPF 的特定功能,且不會遵循安全性、當地語系化和輔助功能等所有最佳做法。 如需 WPF 和 .NET 應用程式開發最佳做法的完整內容,請參閱下列主題:
下一步
在本逐步解說中,您已了解一些使用 Windows Presentation Foundation (WPF) 建立 UI 的技術。 您現在應該對資料繫結 .NET 應用程式的建置組塊有基本的了解。 如需 WPF 架構和程式設計模型的詳細資訊,請參閱下列主題:
如需建立應用程式的詳細資訊,請參閱下列主題: