教程:使用 .NET 创建 WPF 应用

本教程介绍如何使用 Visual Studio 创建 Windows Presentation Foundation (WPF) 应用。 使用 Visual Studio,可以向窗口添加控件并处理事件。 在本教程结束时,你有一个简单的应用,用于向列表框添加名称。

在本教程中,你将:

  • 创建新的 WPF 应用。
  • 向窗口添加控件。
  • 处理控制事件以提供应用功能。
  • 运行应用。

下面是在学习本教程时创建的应用的预览版:

WPF 教程的已完成示例应用

先决条件

创建 WPF 应用

创建新应用的第一步是打开 Visual Studio 并从模板生成应用。

  1. 打开 Visual Studio。

  2. 选择 “创建新项目”。

    Visual Studio 2026 中“开始”对话框的屏幕截图。“创建新项目”按钮突出显示了红色框。

  3. “搜索模板 ”框中,键入 wpf 并等待搜索结果显示。

  4. 代码语言 下拉列表中,选择 C#Visual Basic

  5. 在模板列表中,选择 WPF 应用程序 ,然后选择“ 下一步”。

    重要

    请勿选择 WPF 应用程序(.NET Framework 模板。

    下图显示了 C# 和 Visual Basic .NET 项目模板。 如果应用 了代码语言 筛选器,则会列出相应的模板。

    Visual Studio 的“创建新项目”对话框的屏幕截图,其中突出显示了搜索框中的“wpf”,并突出显示了 WPF 应用程序模板。

  6. “配置新项目 ”窗口中,将 项目名称 设置为 “名称 ”,然后选择“ 下一步”。

    还可以通过调整 位置 路径将项目保存到其他文件夹。

    Visual Studio 2026 中“配置新项目”对话框的屏幕截图。“项目名称”文本框中有“名称”一词,并用红色框突出显示。“下一步”按钮还突出显示了红色框。

  7. 最后,在“Additional information”窗口中,为Framework设置选择.NET 10.0(长期支持),然后选择创建

    Visual Studio 2026 中“其他信息”对话框的屏幕截图。“Framework”下拉列表框已选中“.NET 10(长期支持)”,并突出显示了红色框。“创建”按钮还突出显示了红色框。

Visual Studio 生成应用后,它将打开默认窗口 MainWindow 的 XAML 设计器窗口。 如果设计器不可见,请在“解决方案资源管理器”窗口中双击 MainWindow.xaml 文件以打开设计器。

Visual Studio 的重要部分

在 Visual Studio 中对 WPF 的支持有五个重要组件,可在创建应用时与之交互:

在为 .NET 创建 WPF 项目时,应知道 Visual Studio 2026 的重要组件。

  1. 解决方案资源管理器

    所有项目文件、代码、窗口和资源都将显示在此窗口中。

  2. 属性

    您可以根据所选项的上下文,在此窗口中配置属性设置。 例如,如果从 解决方案资源管理器中选择某个项,将显示与文件相关的设置。 如果选择设计器中的对象,将显示控件或窗口的属性。

  3. 工具箱

    工具箱包含可添加到设计图面的所有控件。 若要将控件添加到当前图面,请双击控件或将控件拖放到设计器。 通常使用 XAML 代码编辑器窗口设计用户界面(UI),同时使用 XAML 设计器窗口预览结果。

  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>

重要

如果要在 Visual Basic 中编码,则 XAML 略有不同,特别是 x:Class=".." 属性。 在 Visual Basic 中,XAML 使用对象的类名,并省略类的命名空间。

为了更好地了解 XAML,让我们将其分解。 XAML 只是 WPF 处理创建 UI 的 XML。 若要了解 XAML,至少应熟悉 XML 的基础知识。

文档根 <Window> 表示 XAML 文件描述的对象类型。 该文件声明八个属性,它们通常属于三个类别:

  • XML 命名空间

    XML 命名空间为 XML 提供结构。 它确定可在文件中声明的 XML 内容。

    xmlns 属性导入整个文件的 XML 命名空间。 在这种情况下,它将映射到 WPF 声明的类型。 其他 XML 命名空间声明前缀,并导入 XAML 文件的其他类型的和对象。 例如, xmlns:local 命名空间声明 local 前缀并映射到项目声明的对象,即代码命名空间中声明的对象 Names

  • x:Class 属性

    此属性将<Window>映射到您的代码定义的类型:即MainWindow.xaml.csMainWindow.xaml.vb文件,这些文件会在C#中映射到Names.MainWindow类,在Visual Basic中映射到MainWindow类。

  • Title 属性

    在 XAML 对象上声明的任何普通属性都设置该对象的属性。 在这种情况下,该 Title 属性设置 Window.Title 属性。

更改窗口

对于我们的示例应用,此窗口太大,标题栏没有描述性。 让我们来解决这个问题。

  1. 首先,按 F5 键或从菜单中选择 “调试>开始调试 ”来运行应用。

    你将看到模板生成的默认窗口,没有任何控件,以及 MainWindow 的标题:

    空白 WPF 应用

  2. 通过将窗口标题从 Title 更改为 Names

  3. 通过将 Height 设置为 180 并将 Width 设置为 260 来更改窗口的大小。

    <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> 控件置于特定的行和列组合中,然后新网格可以定义更多行和列,并具有自己的子级。

网格控件将其子控件放在行和列中。 网格始终声明单个行和列,这意味着,默认情况下网格是单个单元格。 该默认设置不会让你在放置控件方面具有很大的灵活性。

调整此应用所需的控件的网格布局。

  1. <Grid> 元素添加新属性: Margin="10"

    此设置将网格从窗口边缘引入,使其看起来更美观。

  2. 定义两行和两列,将网格划分为四个单元格:

    <Grid Margin="10">
        
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        
    </Grid>
    
  3. 在 XAML 代码编辑器或 XAML 设计器中选择网格。 XAML 设计器显示每行和列:

    在网格上设置边距的 WPF 应用

添加第一个控件

配置网格后,可以开始向其添加控件。 首先,添加标签控件。

  1. <Label>元素内,在行和列定义之后创建一个新的<Grid>元素。 将元素的内容设置为字符串值 Names

    <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

    标签占用窗口的一半,因为它自动定位到网格的第一行和列。 对于第一行,你不需要那么多的空间,因为你只会将该行用于标签。

  2. 将第一个 Height<RowDefinition> 属性从 * 更改为 Auto

    Auto 自动将网格行大小调整为其内容的大小,在本例中为标签控件。

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

    设计器现在显示标签占用少量可用高度。 下一行有更多的空间可供使用。

    在网格中设置边距且在第一行放置标签控件的 WPF 应用

控件放置

让我们谈谈控件的位置。 在上一节中创建的标签将自动放置在网格的第 0 行和第 0 列中。 行和列的编号从 0 开始,递增 1。 控件对网格没有任何了解,控件不定义任何属性来控制其在网格中的位置。

当控件不了解网格时,如何告知控件使用不同的行或列? 附加属性! 网格利用 WPF 提供的属性系统。

网格控件定义了供子控件使用的新属性。 这些属性实际上并不存在于控件本身上,但在控件添加到网格后,这些属性就可供该控件使用。

网格定义了两个属性,用于确定子控件的行和列位置: Grid.RowGrid.Column。 如果省略控件中的这些属性,则默认值为 0。 因此,控件放置在网格的行 0 和列中 0 。 尝试通过将<Label> 控制的位置改变为Grid.Column 属性,然后设置为1

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

请注意,标签移动到第二列。 可以使用Grid.RowGrid.Column附加属性放置要创建的下一个控件。 现在,暂时将标签还原到第 0 列。

创建名称列表框

调整网格大小并创建标签后,请在标签下方的行上添加列表框控件。

  1. <ListBox />控件下声明<Label>控件。

  2. Grid.Row 属性设置为 1

  3. x:Name 属性设置为 lstNames

    命名控件后,可以在后台代码中引用它。 使用 x:Name 属性将名称分配给控件。

XAML 应如下所示:

<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.RowGrid.Column 附加属性来指定控件在网格中的位置,而堆栈面板则自行自动排列。 它按顺序排列其每个子控件。 它互相“堆叠”每个控件。

  1. <StackPanel>控件下声明<ListBox>控件。

  2. Grid.Row 属性设置为 1

  3. Grid.Column 属性设置为 1

  4. 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,与10非常不同。 margin 属性是一种Thickness类型,可以解析和处理这两个值。 厚度定义了矩形框架每一侧的空间,分别是。 如果边距的值为单个值,则它将该值用于所有四侧。

  5. <StackPanel> 控件内部,创建一个 <TextBox /> 控件。

    1. x:Name 属性设置为 txtName
  6. 最后,在<TextBox>之后,仍然在<StackPanel>内部,创建一个<Button>控件。

    1. x:Name 属性设置为 btnAdd
    2. Margin 设置为 0,5,0,0
    3. 将内容设置为 Add Name.

XAML 应如下所示:

<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 属性订阅事件,就像使用它们来设置属性一样。

  1. 找到控件 <Button>

  2. 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>
    
  3. 生成事件处理程序代码。 右键单击 ButtonAddName_Click 并选择“ 转到定义”。

    此操作在后台代码中生成一个与您提供的处理程序名称匹配的方法。

    private void ButtonAddName_Click(object sender, RoutedEventArgs e)
    {
    
    }
    
    Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)
    
    End Sub
    
  4. 接下来,添加以下代码以执行以下三个步骤:

    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
    

运行应用

处理事件后,运行应用。 此时会显示该窗口,你可以在文本框中输入名称。 通过选择按钮添加名称。

在 Visual Studio 2026 中运行用于 .NET 应用的 WPF。