Windows Presentation Foundation 入门

更新:2007 年 11 月

本教程简单介绍了一个 Windows Presentation Foundation (WPF) 应用程序的开发,该应用程序包括多数 WPF 应用程序所共有的元素,即可扩展应用程序标记语言 (XAML) 标记、隐藏代码、应用程序定义、控件、布局、数据绑定和样式。

本主题包括下列各节。

  • 摘要
  • 先决条件
  • 创建应用程序代码文件
  • 生成和运行应用程序
  • 添加布局
  • 添加控件
  • 添加图像和标题
  • 添加代码以处理事件
  • 创建 ExpenseReportPage 的 UI
  • 添加代码以设计控件的样式
  • 将数据绑定到控件
  • 将数据连接到控件
  • 使用数据模板将样式添加到数据
  • 最佳做法
  • 接下来的内容
  • 相关主题

摘要

本教程引导您通过以下步骤完成一个简单的 WPF 应用程序的开发。

  • 定义一个 XAML 标记以设计应用程序的用户界面 (UI) 的外观。

  • 编写代码以生成应用程序的行为。

  • 创建应用程序定义以管理应用程序。

  • 添加控件和布局以构成应用程序 UI。

  • 创建样式,以便为整个应用程序的 UI 创建一致的外观。

  • 将 UI 绑定到数据,以便既可以用数据填充 UI,又可以使数据和 UI 保持同步。

在本教程结束时,您便会生成好一个独立的 Windows 应用程序。使用此应用程序,用户可以查看选定人员的零用金报销单。应用程序由若干在浏览器样式的窗口中承载的 WPF 页面组成。

用于生成此教程的示例代码同时适用于 C# 和 Microsoft Visual Basic .NET;请参见生成 Windows Presentation Foundation 应用程序简介

先决条件

要生成本教程中开发的应用程序,需要安装 Microsoft .NET Framework和 Windows 软件开发工具包 (SDK)。

安装这两个软件包之后,便可从命令窗口中生成应用程序(当然您也可以根据需要使用类似 Microsoft Visual Studio 这样的集成开发环境 (IDE))。要从命令提示窗口中生成,需要使用随 Windows 软件开发工具包 (SDK) 一起安装的命令窗口。可以在下面的菜单位置找到此命令窗口:

  • “开始”菜单 | 所有程序 | Microsoft Windows SDK | CMD 外壳程序

此外,您还可以按照以下步骤打开 Windows 命令提示窗口:

  1. 从“开始”菜单中选择“运行”。

  2. 请输入下列内容:

    C:\WINDOWS\system32\cmd.exe /E:ON /V:ON /T:0E /K "C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\SetEnv.Cmd"

  3. 按“确定”。

请注意,SetEnv.cmd 设置从命令提示窗口中生成 WPF 应用程序所需的环境。

创建应用程序代码文件

在此步骤中,您将创建应用程序基础结构,其中包括一个应用程序定义、两个页面以及一个图像。

  1. 新建一个名为 App.xaml 的 XAML 标记文件。此文件定义 WPF 应用程序,您还可以用它来指定在应用程序启动时自动显示的 UI(在本例中,是下一步创建的 HomePage.xaml)。XAML 标记应类似于下面的代码:

    <Application 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      StartupUri="HomePage.xaml">
    </Application>
    
  2. 新建一个名为 HomePage.xaml 的 XAML 标记文件,这是应用程序启动时显示的第一个页面。HomePage.xaml 将显示一个人员列表以供用户从中选择人员来查看其零用金报销单。将一个 Page 元素添加到 HomePage.xaml,它采用以下配置:

    • 浏览器的标题栏为“ExpenseIt”。

    • 浏览器的宽度为 550 个与设备无关的像素。

    • 浏览器的高度为 350 个与设备无关的像素。

    • 页面的标题为“ExpenseIt - Home”(ExpenseIt - 主页)。

    XAML 标记应类似于下面的代码:

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
    </Page>
    
  3. 新建一个名为 HomePage.xaml.cs 的代码文件。此文件为代码隐藏文件,其中包含用于处理 HomePage.xaml 中声明的事件的代码。您的代码应类似于下面所显示的内容:

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    namespace ExpenseIt
    {
        public partial class HomePage : Page
        {
            public HomePage()
            {
                InitializeComponent();
            }
        }
    }
    
  4. 新建一个名为 ExpenseReportPage.xaml 的 XAML 标记文件。添加一个 Page 元素并将“ExpenseIt - View Expense Report”(ExpenseIt – 查看零用金报销单)设置为页面标题。此页面将显示 HomePage.xaml 中选定的人员的零用金报销单。XAML 标记应类似于下面的代码:

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.ExpenseReportPage"
      Title="ExpenseIt - View Expense Report">
    </Page>
    
  5. 新建一个名为 ExpenseReportPage.xaml.cs 的文件。此文件为代码隐藏文件,它将零用金报销单数据绑定到 ExpenseReportPage.xaml 中定义的 UI。您的代码应类似于下面所显示的内容:

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    namespace ExpenseIt
    {
        public partial class ExpenseReportPage : Page
        {
            public ExpenseReportPage()
            {
                InitializeComponent();
            }
        }
    }
    
  6. 将一个名为 watermark.png 的图像添加到您在上述步骤中创建的五个代码文件所在的文件夹中。您可以创建自己的图像,也可以从示例代码中复制同名的文件。

生成和运行应用程序

在此步骤中,您将使用 MSBuild 生成在前面定义的应用程序。

  1. 新建一个名为 ExpenseIt.csproj 的文件。此文件为 MSBuild 文件,它是一个特殊的 XML 文件,包含应用程序的生成配置,其中包括:

    • 所编译项目的全局生成变量,包括所生成的程序集的名称、要生成的程序集的类型以及所生成的程序集要添加到的文件夹。

    • 对代码文件的引用。

    • 对包含应用程序使用的类型的 Microsoft .NET Framework程序集的引用。

    生成的文件的内容应类似于下面的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
        <PropertyGroup>
            <AssemblyName>ExpenseIt</AssemblyName>
            <TargetType>winexe</TargetType>
            <OutputPath>bin\$(Configuration)\</OutputPath>
        </PropertyGroup>
        <ItemGroup>
            <Reference Include="System"/>
            <Reference Include="System.Xml"/>
            <Reference Include="System.Data"/>
            <Reference Include="WindowsBase"/>
            <Reference Include="PresentationCore"/>
            <Reference Include="PresentationFramework"/>
        </ItemGroup>
        <ItemGroup>
            <ApplicationDefinition Include="App.xaml"/>
            <Page Include="HomePage.xaml"/>
            <Compile Include="HomePage.xaml.cs" />
            <Page Include="ExpenseReportPage.xaml"/>
            <Compile Include="ExpenseReportPage.xaml.cs" />
            <Resource Include="watermark.png"/>
        </ItemGroup>
        <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets"/>
        <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets"/>
    </Project>
    
  2. 打开命令窗口并转到项目文件和应用程序代码文件所在的文件夹。

  3. 从命令提示符处运行下面的命令:

    MSBuild ExpenseIt.csproj

    对于 Microsoft Visual Basic .NET,运行下面的命令:

    MSBuild ExpenseIt.vbproj

    要使用 Visual Studio 编译并运行应用程序,请在 Visual Studio 中打开项目文件,然后按 F5。

说明:

Visual Studio 2005 自动生成项目文件。由于此教程假定没有安装 Visual Studio,因此详细说明了创建项目文件的过程。有关创建 .csproj 文件的更多信息,请参见生成 WPF 应用程序 (WPF)。如果您使用 Visual Studio 来完成本教程,请使用前面的 MSBuild 文本来覆盖生成的 .csproj 文件的内容。

  1. 打开包含所生成的应用程序可执行文件 expenseit.exe 的文件夹。如果是从命令提示符处生成的,则 expenseit.exe 位于以下文件夹中:

    包含应用程序代码文件的文件夹\bin\

    如果 expenseit.exe 是使用 Visual Studio 生成的,则位于以下文件夹中:

    包含应用程序代码文件的文件夹\bin\debug\

  2. 从命令提示符处运行 expenseit.exe。下图显示正在运行的应用程序。

    ExpenseIt 示例屏幕快照

添加布局

布局提供了放置 UI 元素的一种有序方法,并在 UI 调整大小时管理这些元素的大小和位置。通常情况下,您使用下列布局控件之一将布局添加到 UI 中:

上述各控件都支持一种适用于其子元素的特殊布局类型。ExpenseIt 页面可以调整大小,并且每个页面都具有沿其他元素水平和垂直排列的元素。因此,Grid 是应用程序的理想布局元素。

说明:

有关 Panel 元素的更多信息,请参见 面板概述

下面的 XAML 标记通过将一个 Grid 添加到 HomePage.xaml 来创建一个三行一列、边距为 10 像素的表:

  1. 打开 HomePage.xaml

  2. Page 标记之间添加以下 XAML。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
        <Grid Margin="10">
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
        </Grid>
    </Page>
    

添加控件

在此步骤中,更新主页 UI 以显示用户可从中选择人员以查看其零用金报销单的人员列表。为创建此 UI,将下面的元素添加到 HomePage.xaml 中:

  • ListBox(用于人员列表)。

  • Label(用于列表标题)。

  • Button(单击可查看列表中选定的人员的零用金报销单)。

按照下面的步骤更新 HomePage.xaml:

  1. 使用下面的 XAML 覆盖 HomePage.xaml 文件的内容:

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
    
      <Grid Margin="10">
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
          <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
    
        <!-- 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,0" Width="125"
          Height="25" HorizontalAlignment="Right">View</Button>
    
      </Grid>
    
    </Page>
    
  2. 编译并运行应用程序。

下图显示此步骤中的代码创建的控件。

ExpenseIt 示例屏幕快照

添加图像和标题

在此步骤中,使用相应的图像和页面标题来更新主页 UI:

  1. 打开 HomePage.xaml。

  2. 使用下面的 XAML 覆盖 HomePage.xaml 文件的内容:

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
    
      <Grid>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Source="watermark.png" />
          </Canvas>
          <Label VerticalAlignment="Center" FontFamily="Trebuchet MS" 
            FontWeight="Bold" FontSize="18" Foreground="#0066cc">
            View Expense Report
          </Label>
        </DockPanel>
    
        <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
    
          <!-- 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,0" Width="125" 
            Height="25" HorizontalAlignment="Right">View</Button>
    
        </Grid>
    
      </Grid>
    </Page>
    

    此 XAML 按照以下方式更新 Grid

    • 新建一个两行的网格。

    • 将一个带 CanvasImageLabelDockPanel 添加到第一行。DockPanel 跨越第一行的两列,同时 Canvas 停靠在左侧,这样 Label 就可以与 Image 重叠。

    • 使用 Image 元素的 Source 属性指定源图像 watermark.png。

    • 将标题文本“View Expense Report”(查看零用金报销单)添加到 Label

    • 使用 CanvasLabel 的属性配置其外观和大小。

    • 将 HomePage.xaml 最初包含的网格移到新网格的第二行第二列。

  3. 编译并运行应用程序。

下图显示了此步骤的结果。

ExpenseIt 示例屏幕快照

添加代码以处理事件

  1. 打开 HomePage.xaml。

  2. 使用下面的代码覆盖上一步中定义的 Button 元素。

    ...
    <!-- View report button -->
    <Button Grid.Column="0" Grid.Row="2" Width="125" Height="25" 
      Margin="0,10,0,0" HorizontalAlignment="Right" 
      Click="viewButton_Click">View</Button>
    ...
    
    说明:

    要处理的 Button 事件的名称是 Click。开发人员定义的事件处理程序的名称是 viewButton_Click。此事件处理程序注册给 Button 控件的 Click 事件。

  3. 打开在此教程的创建应用程序代码文件步骤中创建的 HomePage.xaml.cs。

  4. 使用下面的代码覆盖此文件的内容。此操作添加代码来处理 Click 事件,从而可以导航到 ExpenseReportPage.xaml 文件。

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    namespace ExpenseIt
    {
        public partial class HomePage : Page
        {
            public HomePage()
            {
                InitializeComponent();
            }
            private void viewButton_Click(object sender, RoutedEventArgs args)
            {
                // View Expense Report
                ExpenseReportPage expenseReportPage = new ExpenseReportPage();
                this.NavigationService.Navigate(expenseReportPage);
            }
        }
    }
    

创建 ExpenseReportPage 的 UI

ExpenseReportPage.xaml 显示从 HomePage.xaml 中选定的人员的零用金报销单。下面的更新添加控件和布局以便为 ExpenseReportPage.xaml 创建基本的 UI。此外,还为各个 UI 元素添加背景色和填充色。

  1. 打开 ExpenseReportPage.xaml 文件并添加以下代码。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.ExpenseReportPage"
      Title="ExpenseIt - View Expense Report">
    
      <Grid>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Source="watermark.png" />
          </Canvas>
          <Label VerticalAlignment="Center" FontFamily="Trebuchet MS" 
            FontWeight="Bold" FontSize="18" Foreground="#0066cc">
            Expense Report For:
          </Label>
        </DockPanel>
    
        <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="3">
    
            <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition Width="10" />
              <ColumnDefinition />
            </Grid.ColumnDefinitions>
    
            <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition />
            </Grid.RowDefinitions>
    
            <!-- Expense type list -->
            <Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4">
              <Label VerticalAlignment="Center" Foreground="White">Expense Type</Label>
            </Border>
            <ListBox Grid.Column="0" Grid.Row="1" />
    
            <!-- Amount list -->
            <Border Grid.Column="2" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4">
              <Label VerticalAlignment="Center" Foreground="White">Amount</Label>
            </Border>
            <ListBox Grid.Column="2" Grid.Row="1" />
    
          </Grid>
        </Grid>
      </Grid>
    </Page>
    
  2. 编译并运行应用程序。

下图显示添加到 ExpenseReportPage.xaml 中的 UI 元素。

ExpenseIt 示例屏幕快照

添加代码以设计控件的样式

通常情况下,UI 中所有同类型元素的外观可以保持一致。UI 通过样式使外观可以重用于多个元素。样式的可重用性有助于简化 XAML 标记的创建和管理。此步骤将前面的步骤中定义的各元素的属性替换为样式:

  1. 打开在此教程的创建应用程序代码文件步骤中创建的 App.xaml 文件。

  2. 使用下面的 XAML 标记覆盖此文件的内容:

    <Application 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      StartupUri="HomePage.xaml">
    
      <Application.Resources>
    
        <!-- Background image style -->
        <Style x:Key="backgroundImageStyle">
          <Setter Property="Image.Source" Value="watermark.png"/>
        </Style>
    
        <!-- 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>
    
        <!-- 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>
    
      </Application.Resources>
    
    </Application>
    

    此 XAML 标记添加以下样式:

    • headerTextStyle:设置页面标题 Label 的格式。

    • labelStyle:设置 Label 标签的格式。

    • listHeaderStyle:设置列表标题 Border 控件的格式。

    • listHeaderTextStyle:设置列表标题 Label 的格式。

    • buttonStyle:设置 HomePage.xaml 上的按钮的格式。

    请注意,样式是一种资源,也是 Application.Resources 属性元素的子级。这里,样式将应用于应用程序中的所有元素。有关如何使用 .NET Framework 应用程序中的资源的示例,请参见如何:使用应用程序资源

  3. 打开 HomePage.xaml。

  4. 使用下面的代码覆盖此文件的内容。此步骤将各元素特定于外观的属性替换为相应的样式。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
    
      <Grid>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Style="{StaticResource backgroundImageStyle}" />
          </Canvas>
          <Label Style="{StaticResource headerTextStyle}">View Expense Report</Label>
        </DockPanel>
    
        <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
    
          <!-- People list -->
          <Border Grid.Column="0" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
            <Label Style="{StaticResource listHeaderTextStyle}">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" Style="{StaticResource buttonStyle}" 
            Click="viewButton_Click">View
          </Button>
    
        </Grid>
    
      </Grid>
    
    </Page>
    
  5. 打开 ExpenseReportPage.xaml。

  6. 使用下面的代码覆盖此文件的内容。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.ExpenseReportPage"
      Title="ExpenseIt - View Expense Report">
    
      <Grid>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Style="{StaticResource backgroundImageStyle}" />
          </Canvas>
          <Label Style="{StaticResource headerTextStyle}">Expense Report For:</Label>
        </DockPanel>
    
        <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="3">
    
            <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition Width="10" />
              <ColumnDefinition />
            </Grid.ColumnDefinitions>
    
            <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition />
            </Grid.RowDefinitions>
    
            <!-- Expense type list -->
            <Border Grid.Column="0" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
              <Label Style="{StaticResource listHeaderTextStyle}">Expense Type</Label>
            </Border>
            <ListBox Grid.Column="0" Grid.Row="1" />
    
            <!-- Amount list -->
            <Border Grid.Column="2" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
              <Label Style="{StaticResource listHeaderTextStyle}">Amount</Label>
            </Border>
            <ListBox Grid.Column="2" Grid.Row="1" />
    
          </Grid>
    
        </Grid>
    
      </Grid>
    
    </Page>
    
  7. 编译并运行应用程序。在此步骤中添加 XAML 标记之后,应用程序看上去与使用样式更新之前一样。

将数据绑定到控件

此步骤创建要绑定到各个控件的 XML 数据:

  1. 打开 HomePage.xaml。

  2. 使用下面的 XAML 标记覆盖此文件的内容。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.HomePage"
      WindowTitle="ExpenseIt"
      Title="ExpenseIt - Home" 
      WindowWidth="550" WindowHeight="380">
    
      <Grid>
    
        <Grid.Resources>
    
          <!-- Expense Report Data -->
          <XmlDataProvider x:Key="ExpenseDataSource" XPath="Expenses">
            <x:XData>
              <Expenses >
                <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>
    
          <!-- Name item template -->
          <DataTemplate x:Key="nameItemTemplate">
            <Label Content="{Binding XPath=@Name}"/>
          </DataTemplate>
    
        </Grid.Resources>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Style="{StaticResource backgroundImageStyle}" />
          </Canvas>
          <Label Style="{StaticResource headerTextStyle}">View Expense Report</Label>
        </DockPanel>
    
        <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
    
          <!-- People list -->
          <Border Grid.Column="0" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
            <Label Style="{StaticResource listHeaderTextStyle}">Names</Label>
          </Border>
          <ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1" 
            ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}" 
            ItemTemplate="{StaticResource nameItemTemplate}" />
    
          <!-- View report button -->
          <Button Grid.Column="0" Grid.Row="2" Style="{StaticResource buttonStyle}" 
            Click="viewButton_Click">View</Button>
    
        </Grid>
    
      </Grid>
    
    </Page>
    

    请注意数据作为 Grid 资源创建。

将数据连接到控件

在此步骤中,您将编写代码来检索从 HomePage 上的人员列表中选定的当前项,并在实例化过程中将对该当前项的引用传递给 ExpenseReportPage 的构造函数。ExpenseReportPage 使用已传入的项设置数据上下文,这就是 ExpenseReportPage.xaml 中定义的控件要绑定的内容。

  1. 打开 HomePage.xaml.cs。

  2. 使用下面的代码覆盖此文件的内容。

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    namespace ExpenseIt
    {
        public partial class HomePage : Page
        {
            public HomePage()
            {
                InitializeComponent();
            }
    
            private void viewButton_Click(object sender, RoutedEventArgs args)
            {
                // Create a new expense report page and pass it the selected person
                // by using the non-default constructor.
                ExpenseReportPage expenseReportPage = 
                    new ExpenseReportPage(this.peopleListBox.SelectedItem);
    
                // Navigate to the expense report page,
                this.NavigationService.Navigate(expenseReportPage);
            }
        }
    }
    
  3. 打开 ExpenseReportPage.xaml.cs。

  4. 使用下面的代码覆盖此文件的内容。

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    namespace ExpenseIt
    {
        public partial class ExpenseReportPage : Page
        {
            public ExpenseReportPage(object data)
            {
                InitializeComponent();
    
                // Bind to expense report data.
                this.DataContext = data;
            }
        }
    }
    

使用数据模板将样式添加到数据

在此步骤中,使用数据模板更新数据绑定列表中各项的 UI:

  1. 打开 ExpenseReportPage.xaml。

  2. 使用下面的代码覆盖此文件的内容。

    <Page 
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="ExpenseIt.ExpenseReportPage"
      Title="ExpenseIt - View Expense Report">
    
      <Grid>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
    
        <DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
          <Canvas DockPanel.Dock="Left" Width="230" Height="100">
            <Image Style="{StaticResource backgroundImageStyle}" />
          </Canvas>
          <Label Style="{StaticResource headerTextStyle}">Expense Report For:</Label>
        </DockPanel>
    
        <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <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>
    
          <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 Content="{Binding XPath=@Name}" Style="{StaticResource labelStyle}"/>
          </StackPanel>
    
          <!-- Department -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
            <Label Style="{StaticResource labelStyle}">Department:</Label>
            <Label Content="{Binding XPath=@Department}" Style="{StaticResource labelStyle}"/>
          </StackPanel>
          <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3">
    
            <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition Width="10" />
              <ColumnDefinition />
            </Grid.ColumnDefinitions>
    
            <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition />
            </Grid.RowDefinitions>
    
            <!-- Expense type list -->
            <Border Grid.Column="0" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
              <Label Style="{StaticResource listHeaderTextStyle}">Expense Type</Label>
            </Border>
            <ListBox Grid.Column="0" Grid.Row="1" ItemsSource="{Binding XPath=Expense}" 
              ItemTemplate="{StaticResource typeItemTemplate}" />
    
            <!-- Amount list -->
            <Border Grid.Column="2" Grid.Row="0" Style="{StaticResource listHeaderStyle}">
              <Label Style="{StaticResource listHeaderTextStyle}">Amount</Label>
            </Border>
            <ListBox Grid.Column="2" Grid.Row="1" ItemsSource="{Binding XPath=Expense}" 
              ItemTemplate="{StaticResource amountItemTemplate}" />
    
          </Grid>
    
        </Grid>
    
      </Grid>
    
    </Page>
    
  3. 编译并运行应用程序。

请注意数据模板定义为 Grid 资源。

下面两个图显示的是应用了控件、布局、样式、数据绑定和数据模板的 ExpenseIt 应用程序的两个页面:

ExpenseIt 示例屏幕快照

最佳做法

本示例演示 Windows Presentation Foundation 的特定功能,因此未遵循应用程序开发的最佳做法。有关 Windows Presentation Foundation (WPF) 和 Microsoft .NET Framework 应用程序开发的最佳做法的全面介绍,请相应地参考以下主题:

辅助功能 - 辅助功能最佳方案

安全 - Windows Presentation Foundation 安全性

本地化 - WPF 全球化和本地化概述

优化 WPF 应用程序性能

接下来的内容

现在,您已具备充分的技能来使用 Windows Presentation Foundation (WPF) 创建 UI。接下来您应当对数据绑定的 .NET Framework 应用程序的基本构造块进行全面的了解。本主题并未涵盖所有信息,不过您现在应该也可以在本主题所介绍的方法之外自己发现一些可能的方法。

Panel 在 面板概述中有更详细的讨论。数据模板化在数据模板化概述中有更深入的讨论。

请参见

概念

布局系统

面板概述

数据绑定概述

数据模板化概述

生成 WPF 应用程序 (WPF)