WPF 窗口概述

用户通过窗口与 Windows Presentation Foundation (WPF) 独立应用程序交互。 窗口的主要用途是托管使数据可视化并使用户能够与数据交互的内容。 独立 WPF 应用程序使用 Window 类提供自己的窗口。 本主题先介绍 Window,然后讲述在独立应用程序中创建和管理窗口的基础知识。

注意

浏览器托管的 WPF 应用程序,包括 XAML 浏览器应用程序 (XBAP) 和松散的 Extensible Application Markup Language (XAML) 页面,不提供自己的窗口。 相反,它们托管在 Windows Internet Explorer 提供的窗口中。 请参阅 WPF XAML 浏览器应用程序概述

窗口类

下图展示了窗口的构成部分:

Screenshot that shows window elements.

窗口分为两个区域:非工作区和工作区。

窗口的非工作区由 WPF实现,它包括大多数窗口所共有的窗口部分,包括:

  • 边框。

  • 标题栏。

  • 图标。

  • “最小化”、“最大化”和“还原”按钮。

  • “关闭”按钮。

  • “系统”菜单,其中包含允许用户最小化、最大化、还原、移动和关闭窗口以及重设窗口大小的菜单项。

窗口的工作区是窗口的非工作区内部的区域,由开发人员用于添加特定于应用程序的内容,例如菜单栏、工具栏和控件。

在 WPF 中,窗口由用于执行以下操作的 Window 类封装:

  • 显示窗口。

  • 配置窗口的大小、位置和外观。

  • 托管特定于应用程序的内容。

  • 管理窗口的生存期。

实现窗口

典型窗口的实现既包括外观又包括行为,外观定义用户看到的窗口的样子,行为定义用户与之交互时窗口的运行方式。 在 WPF 中,可以使用代码或 XAML 标记实现窗口的外观和行为。

但在一般情况下,窗口的外观使用 XAML 标记实现,行为使用代码隐藏实现,如以下示例所示。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MarkupAndCodeBehindWindow">
  
  <!-- Client area (for content) -->
  
</Window>
using System.Windows;

namespace SDKSample
{
    public partial class MarkupAndCodeBehindWindow : Window
    {
        public MarkupAndCodeBehindWindow()
        {
            InitializeComponent();
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class MarkupAndCodeBehindWindow
        Inherits Window
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

若要使 XAML 标记文件和代码隐藏文件配合工作,需要满足以下要求:

  • 在标记中,Window 元素必须包含 x:Class 属性。 生成应用程序时,标记文件中存在 x:Class 会使 Microsoft 生成引擎 (MSBuild) 创建派生自 Windowpartial 类,并且名称由 x:Class 属性指定。 这要求为 XAML 架构 (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml") 添加 XML 命名空间声明。 生成的 partial 类实现 InitializeComponent 方法,注册事件和设置在标记中实现的属性时将调用此方法。

  • 在代码隐藏中,类必须是 partial 类、名称必须是标记中 x:Class 属性指定的相同名称,并且它必须派生自 Window。 这样,代码隐藏文件就可以与生成应用程序时为标记文件生成的 partial 类(请参阅生成 WPF 应用程序)相关联。

  • 在代码隐藏中,Window 类必须实现调用 InitializeComponent 方法的构造函数。 InitializeComponent 由标记文件已生成的 partial 类实现,用以注册事件并设置标记中定义的属性。

注意

使用 Visual Studio 将新的 Window 添加到项目时,Window 通过同时使用标记和代码隐藏实现,并且包括必要的配置来创建此处所述的标记文件和代码隐藏文件之间的关联。

进行了此配置后,可以专注于在 XAML 标记中定义窗口的外观,并可在代码隐藏中实现窗口的行为。 以下示例显示一个带按钮的窗口(在 XAML 标记中实现)和该按钮 Click 事件的事件处理程序(在代码隐藏中实现)。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MarkupAndCodeBehindWindow">
  <!-- Client area (for content) -->
  <Button Click="button_Click">Click This Button</Button>
</Window>
using System.Windows;

namespace SDKSample
{
    public partial class MarkupAndCodeBehindWindow : Window
    {
        public MarkupAndCodeBehindWindow()
        {
            InitializeComponent();
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button was clicked.");
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class MarkupAndCodeBehindWindow
        Inherits Window
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            MessageBox.Show("Button was clicked.")
        End Sub
    End Class
End Namespace

为 MSBuild 配置窗口定义

实现窗口的方式决定为 MSBuild 配置窗口的方式。 对于使用 XAML 标记和代码隐藏定义的窗口:

  • XAML 标记文件配置为 MSBuild Page 项。

  • 代码隐藏文件配置为 MSBuild Compile 项。

这显示在以下 MSBuild 项目文件中。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
    ...  
    <Page Include="MarkupAndCodeBehindWindow.xaml" />  
    <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />  
    ...  
</Project>  

有关生成 WPF 应用程序的信息,请参阅生成 WPF 应用程序

窗口生存期

与所有类一样,窗口也有生存期,开始于首次实例化窗口,在这之后将打开、激活、停用直至最终关闭窗口。

打开窗口

若要打开窗口,首先要创建窗口实例,下面的示例演示此操作。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    Startup="app_Startup">
</Application>
using System.Windows;
namespace SDKSample
{
    public partial class App : Application
    {
        void app_Startup(object sender, StartupEventArgs e)
        {
            // Create a window
            MarkupAndCodeBehindWindow window = new MarkupAndCodeBehindWindow();

            // Open a window
            window.Show();
        }
    }
}

在本示例中,MarkupAndCodeBehindWindow 在应用程序启动时实例化,此过程在引发 Startup 事件时发生。

实例化窗口后,对其的引用将自动添加到由 Application 对象管理的窗口列表(请参阅 Application.Windows)。 此外,默认情况下,要实例化的第一个窗口由 Application 设置为主应用程序窗口(请参阅 Application.MainWindow)。

最后,通过调用 Show 方法打开窗口;结果如下图所示。

A Window Opened by calling Window.Show

通过调用 Show 打开的窗口是非模式窗口,这意味着应用程序运行的模式允许用户在同一应用程序中激活其他窗口。

注意

调用 ShowDialog 可以模式的形式打开诸如对话框等窗口。 有关详细信息,请参阅对话框概述

调用 Show 时,窗口先执行初始化工作,然后显示窗口以建立让窗口可以接收用户输入的基础结构。 初始化窗口时,将引发 SourceInitialized 事件并显示窗口。

作为快捷方式,StartupUri 可以设置为指定应用程序启动时自动打开的第一个窗口。

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

应用程序启动时,StartupUri 值指定的窗口将以非模式形式打开;在内部,通过调用该窗口的 Show 方法打开它。

窗口所有权

使用 Show 方法打开的窗口与创建它的窗口没有隐式关系;用户可以与这两个窗口分别进行独立的交互,这意味着任意一个窗口均可执行以下操作:

  • 覆盖另一个窗口(除非其中一个窗口的 Topmost 属性设置为 true)。

  • 在不影响另一个窗口的情况下最小化、最大化和还原。

某些窗口要求与打开它们的窗口保持某种关系。 例如,集成开发环境 (IDE) 应用程序可能打开属性窗口和工具窗口,这些窗口的典型行为是覆盖创建它们的窗口。 此外,此类窗口应始终与创建它们的窗口一起关闭、最小化、最大化和还原。 可以通过让一个窗口拥有另一个窗口来建立这种关系,通过使用对所有者窗口的引用设置被拥有窗口的 Owner 属性来实现。 这在下面的示例中显示。

// Create a window and make this window its owner
Window ownedWindow = new Window();
ownedWindow.Owner = this;
ownedWindow.Show();
' Create a window and make this window its owner
Dim ownedWindow As New Window()
ownedWindow.Owner = Me
ownedWindow.Show()

建立所有权后:

  • 被拥有的窗口可以通过检查其 Owner 属性的值来引用它的所有者窗口。

  • 所有者窗口可以通过检查其 OwnedWindows 属性的值来发现它拥有的所有窗口。

防止窗口激活

在一些情况下,不应在显示窗口时将其激活,例如 Internet Messenger 风格的应用程序的对话窗口或电子邮件应用程序的通知窗口。

如果应用程序的窗口在显示时不应激活,可以在首次调用 Show 方法之前,先将其 ShowActivated 属性设置为 false。 结果是:

  • 不会激活窗口。

  • 未引发窗口的 Activated 事件。

  • 当前激活的窗口保持激活状态。

但是,只要用户通过单击工作区或非工作区激活了窗口,窗口就会变为激活状态。 在这种情况下:

  • 已激活窗口。

  • 已引发窗口的 Activated 事件。

  • 停用之前激活的窗口。

  • 然后按照预期,响应用户操作引发窗口的 DeactivatedActivated 事件。

窗口激活

首次打开窗口时,它即成为活动窗口(除非在显示时 ShowActivated 设置为 false)。 活动窗口是当前捕获用户输入(例如击键和鼠标单击)的窗口。 当窗口处于活动状态时,它会引发 Activated 事件。

注意

第一次打开窗口时,只有当引发 Activated 后才会引发 LoadedContentRendered 事件。 记住这一点,在引发 ContentRendered 时,实际上就可认为窗口已打开。

某个窗口成为活动窗口后,用户可以在同一应用程序内激活其他窗口,或者激活其他应用程序。 发生这种情况时,将停用当前的活动窗口,并引发 Deactivated 事件。 同样,如果用户选择当前停用的窗口,该窗口将再次成为活动窗口,并引发 Activated 事件。

处理 ActivatedDeactivated 的一个常见原因是为了启用和禁用仅在窗口处于活动状态时才能够运行的功能。 例如,一些窗口显示需要用户持续输入或关注的交互式内容,这些内容包括游戏和视频播放器。 以下示例是简化的视频播放器,展示如何处理 ActivatedDeactivated 以实现此行为。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.CustomMediaPlayerWindow"
    Activated="window_Activated"
    Deactivated="window_Deactivated">

    <!-- Media Player -->
    <MediaElement 
      Name="mediaElement" 
      Stretch="Fill" 
      LoadedBehavior="Manual" 
      Source="numbers.wmv" />

</Window>
using System;
using System.Windows;

namespace SDKSample
{
    public partial class CustomMediaPlayerWindow : Window
    {
        public CustomMediaPlayerWindow()
        {
            InitializeComponent();
        }

        void window_Activated(object sender, EventArgs e)
        {
            // Recommence playing media if window is activated
            this.mediaElement.Play();
        }

        void window_Deactivated(object sender, EventArgs e)
        {
            // Pause playing if media is being played and window is deactivated
            this.mediaElement.Pause();
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class CustomMediaPlayerWindow
        Inherits Window
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub window_Activated(ByVal sender As Object, ByVal e As EventArgs)
            ' Recommence playing media if window is activated
            Me.mediaElement.Play()
        End Sub

        Private Sub window_Deactivated(ByVal sender As Object, ByVal e As EventArgs)
            ' Pause playing if media is being played and window is deactivated
            Me.mediaElement.Pause()
        End Sub
    End Class
End Namespace

停用某个窗口后,其他类型的应用程序可能仍会在后台运行代码。 例如,在用户使用其他应用程序时,邮件客户端可能会继续轮询邮件服务器。 类似的应用程序在主窗口停用时,通常将提供不同或其他的行为。 对于邮件程序,这可能意味着将新邮件项添加到收件箱和将通知图标添加到系统任务栏。 通知图标只需在邮件窗口处于非活动状态时显示,可通过检查 IsActive 属性来确定这种状态。

完成某个后台任务后,窗口可能需要通过调用 Activate 方法来更迫切地通知用户。 如果在调用 Activate 时,用户正与其他激活的应用程序进行交互,窗口的任务栏按钮会闪烁。 但是,如果用户正在与当前应用程序交互,则调用 Activate 会将窗口置于前景。

注意

可以使用 Application.ActivatedApplication.Deactivated 事件处理应用程序范围的激活。

关闭窗口

窗口的生存期在用户关闭它时终止。 可以使用非工作区中的元素关闭窗口,这些元素包括:

  • “系统”菜单的“关闭”项。

  • 按 ALT+F4。

  • 按“关闭”按钮。

可以向工作区提供其他关闭窗口的机制,较为常见的机制包括:

  • “文件”菜单中的“退出”项,通常用于主应用程序窗口。

  • “文件”菜单中的“关闭”项,通常位于辅助应用程序窗口中。

  • “取消”按钮,通常位于模式对话框中。

  • “关闭”按钮,通常位于非模式对话框中。

若要为响应其中一种自定义机制而关闭窗口,需要调用 Close 方法。 以下示例实现通过选择“文件”菜单上的“退出”关闭窗口的功能

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.WindowWithFileExit">
  
  <Menu>
    <MenuItem Header="_File">
      <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
    </MenuItem>
  </Menu>
  
</Window>
using System.Windows;

namespace SDKSample
{
    public partial class WindowWithFileExit : System.Windows.Window
    {
        public WindowWithFileExit()
        {
            InitializeComponent();
        }

        void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Close this window
            this.Close();
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class WindowWithFileExit
        Inherits System.Windows.Window
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub fileExitMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Close this window
            Me.Close()
        End Sub
    End Class
End Namespace

窗口关闭时,会引发两个事件:ClosingClosed

Closing 在窗口关闭前引发,并提供一种可以阻止窗口关闭的机制。 阻止窗口关闭的一个常见原因是窗口内容包含修改的数据。 在这种情况下,处理 Closing 事件可以确定数据是否为已更新,如果已更新,询问用户是在不保存数据的情况下继续关闭窗口,还是取消关闭窗口。 以下示例演示了处理 Closing 的关键方面。

using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // window

namespace CSharp
{
    public partial class DataWindow : Window
    {
        // Is data dirty
        bool isDataDirty = false;

        public DataWindow()
        {
            InitializeComponent();
        }

        void documentTextBox_TextChanged(object sender, EventArgs e)
        {
            this.isDataDirty = true;
        }

        void DataWindow_Closing(object sender, CancelEventArgs e)
        {
            MessageBox.Show("Closing called");

            // If data is dirty, notify user and ask for a response
            if (this.isDataDirty)
            {
                string msg = "Data is dirty. Close without saving?";
                MessageBoxResult result =
                  MessageBox.Show(
                    msg,
                    "Data App",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Warning);
                if (result == MessageBoxResult.No)
                {
                    // If user doesn't want to close, cancel closure
                    e.Cancel = true;
                }
            }
        }
    }
}
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' window

Namespace VisualBasic
    Partial Public Class DataWindow
        Inherits Window
        ' Is data dirty
        Private isDataDirty As Boolean = False

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub documentTextBox_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
            Me.isDataDirty = True
        End Sub

        Private Sub DataWindow_Closing(ByVal sender As Object, ByVal e As CancelEventArgs)
            MessageBox.Show("Closing called")

            ' If data is dirty, notify user and ask for a response
            If Me.isDataDirty Then
                Dim msg As String = "Data is dirty. Close without saving?"
                Dim result As MessageBoxResult = MessageBox.Show(msg, "Data App", MessageBoxButton.YesNo, MessageBoxImage.Warning)
                If result = MessageBoxResult.No Then
                    ' If user doesn't want to close, cancel closure
                    e.Cancel = True
                End If
            End If
        End Sub
    End Class
End Namespace

Closing 事件处理程序传递 CancelEventArgs,它会实现 BooleanCancel 属性,将该属性设置为 true 以防止窗口关闭。

如果未处理 Closing,或者已处理但未取消,窗口将关闭。 在窗口真正关闭前,将引发 Closed。 此时,无法阻止窗口关闭。

注意

可将应用程序配置为在出现以下情况时自动关闭:主应用程序窗口关闭(请参阅 MainWindow)或最后一个窗口关闭。 有关详细信息,请参阅 ShutdownMode

虽然窗口可通过非工作区和工作区中提供的机制显式关闭,但它也可能因为应用程序或 Windows 的其他部分中的行为而隐式关闭,行为包括:

注意

窗口在关闭后无法重新打开。

窗口生存期事件

下图显示窗口生存期中的主体事件的顺序:

Diagram that shows events in a window's lifetime.

下图显示窗口(显示时没有激活)生存期中的主体事件的顺序(显示窗口之前将 ShowActivated 设置为 false):

Diagram that shows events in a window's lifetime without activation.

窗口位置

当窗口打开时,它在相对于桌面的 x 和 y 维度中有一个位置。 可以通过检查 LeftTop 来确定此位置。 设置这些属性可以更改窗口的位置。

还可通过使用以下任一 WindowStartupLocation 枚举值来设置 WindowStartupLocation 属性,从而指定 Window 首次出现时的初始位置:

如果将启动位置指定为 Manual,并且未设置 LeftTop 属性,Window 将要求 Windows 指定其显示位置。

最顶层窗口和 Z 顺序

除了有 x 和 y 位置外,窗口还在 z 维度中有一个位置,该位置确定窗口相对于其他窗口的垂直位置。 它称为窗口的 z 顺序,并且有两种类型:正常 z 顺序和最顶层 z 顺序。 正常 z 顺序中的窗口位置取决于窗口当前是否处于活动状态。 默认情况下,窗口位于正常 z 顺序中。 最顶层 z 顺序中的窗口位置也取决于它当前是否处于活动状态。 此外,最顶层 z 顺序中的窗口始终位于正常 z 顺序中的窗口之上。 窗口通过将其 Topmost 属性设置为 true 来采用最顶层 z 顺序。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Topmost="True">
</Window>

在每个 z 顺序中,当前的活动窗口显示在同一 z 顺序中所有其他窗口之上。

窗口大小

除了拥有桌面位置外,窗口还有大小,大小由多个属性确定,包括各种宽度和高度属性以及 SizeToContent

使用 MinWidthWidthMaxWidth 管理窗口在生存期内可以具有的宽度范围,配置方式如以下示例所示。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinWidth="300" Width="400" MaxWidth="500">
</Window>

窗口高度由 MinHeightHeightMaxHeight 管理,配置方式如以下示例所示。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinHeight="300" Height="400" MaxHeight="500">
</Window>

由于各种宽度值和高度值各自指定了一个范围,所以大小可调整大小的窗口的宽度和高度可以是相应维度中指定范围内的任何值。 若要检测其当前的宽度和高度,请分别检查 ActualWidthActualHeight

如果希望窗口的宽度和高度适应窗口内容的大小,可以使用 SizeToContent 属性,它具有以下值:

以下示例显示了一个窗口,它在第一次显示时即自动调整垂直方向和水平方向上的大小以适应内容。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    SizeToContent="WidthAndHeight">
</Window>

以下示例显示如何在代码中设置 SizeToContent 属性以指定重设窗口大小使其适应内容的方式。


// Manually alter window height and width
this.SizeToContent = SizeToContent.Manual;

// Automatically resize width relative to content
this.SizeToContent = SizeToContent.Width;

// Automatically resize height relative to content
this.SizeToContent = SizeToContent.Height;

// Automatically resize height and width relative to content
this.SizeToContent = SizeToContent.WidthAndHeight;

' Manually alter window height and width
Me.SizeToContent = SizeToContent.Manual

' Automatically resize width relative to content
Me.SizeToContent = SizeToContent.Width

' Automatically resize height relative to content
Me.SizeToContent = SizeToContent.Height

' Automatically resize height and width relative to content
Me.SizeToContent = SizeToContent.WidthAndHeight

大小调整属性的优先级顺序

从根本上说,窗口的各种大小属性可以结合使用,以定义可调整大小的窗口的宽度和高度范围。 为了确保保持有效的范围,Window 将使用以下优先级顺序计算大小属性的值。

对于高度属性:

  1. FrameworkElement.MinHeight

  2. FrameworkElement.MaxHeight

  3. SizeToContent.Height/SizeToContent.WidthAndHeight

  4. FrameworkElement.Height

对于宽度属性:

  1. FrameworkElement.MinWidth

  2. FrameworkElement.MaxWidth

  3. SizeToContent.Width/SizeToContent.WidthAndHeight

  4. FrameworkElement.Width

优先级顺序还可以确定窗口在最大化时的大小,此时的窗口大小由 WindowState 属性管理。

窗口状态

可调整大小的窗口在生存期中拥有三种状态:正常、最小化和最大化。 正常是窗口的默认状态。 这种状态下的窗口允许用户使用重设大小手柄或边框移动窗口和重设其大小(前提是大小可以重设)。

如果 ShowInTaskbar 设置为 true,则最小化状态下的窗口将折叠到任务栏按钮;否则,它将尽可能折叠到最小大小,并将自己重新定位到桌面的左下角。 虽然不在任务栏显示的最小化窗口可以在桌面上四处拖动,但这两种类型的最小化窗口都不可以使用边框或重设大小手柄重设窗口大小。

具有最大化状态的窗口会扩展到它能具有的最大大小,这不能超过 MaxWidthMaxHeightSizeToContent 属性指定的大小。 与最小化窗口一样,最大化窗口无法使用重设大小手柄或通过拖动边框来重设大小。

注意

即使窗口当前已最大化或最小化,窗口的 TopLeftWidthHeight 属性的值也始终表示正常状态的值。

可以通过设置 WindowState 属性来配置窗口的状态,该属性可以具有以下 WindowState 枚举值之一:

以下示例显示如何创建在打开时最大化显示的窗口。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowState="Maximized">
</Window>

通常,应设置 WindowState 以配置窗口的初始状态。 显示可调整大小的窗口后,用户可以按窗口标题栏上的“最小化”、“最大化”和“还原”按钮来更改窗口状态。

窗口外观

通过将特定于窗口的内容(例如按钮、标签和文本框)添加到窗口的工作区可以更改它的外观。 为配置非工作区,Window 提供几个属性,包括用于设置窗口图标的 Icon 和用于设置其标题的 Title

还可以通过配置窗口的重设大小模式、窗口样式,以及窗口是否显示为桌面任务栏中的按钮,更改非工作区边框的外观和行为。

重设大小模式

根据 WindowStyle 属性,可以控制用户如何(以及是否能够)重设窗口大小。 窗口样式的选择影响用户是否可以通过使用鼠标拖动边框来重设窗口大小、非工作区是否会显示“最小化”、“最大化”和“重设大小”按钮以及在显示时,这些按钮是否已启用

可以通过设置窗口的 ResizeMode 属性来配置重设窗口大小的方式,该属性可以是下列 ResizeMode 枚举值之一:

WindowStyle 一样,窗口的重设大小模式在生存期中不太可能更改,这意味着它最有可能在 XAML 标记中进行设置。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ResizeMode="CanResizeWithGrip">
</Window>

请注意,可以通过检查 WindowState 属性来检测是否已最大化、最小化或还原窗口。

窗口样式

从窗口非工作区公开的边框适用于大多数应用程序。 但是,有时候会需要不同类型的边框,或者根本不需要边框,具体取决于窗口类型。

若要控制窗口的边框类型,请将其 WindowStyle 属性设置为以下 WindowStyle 枚举值之一:

下图显示了这些窗口样式的效果:

Illustration of window border styles.

可以使用 XAML 标记或代码设置 WindowStyle;由于它在窗口生存期内不太可能发生更改,所以最有可能使用 XAML 标记对其进行配置。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowStyle="ToolWindow">
</Window>

非矩形窗口样式

在另外一些情况下,WindowStyle 提供的边框样式不能满足需要。 例如,可能希望创建一个带有非矩形边框(如 Windows Media Player 所使用的边框)的应用程序。

下图中显示的对话气泡框就是一个例子:

A speech bubble window that says Drag Me.

可以通过将 WindowStyle 属性设置为 None,并使用 Window 为透明度提供的特殊支持,来创建这种类型的窗口。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowStyle="None"
    AllowsTransparency="True"
    Background="Transparent">
</Window>

多个值组合起来可以指示窗口呈现完全透明的效果。 在这种状态下,无法使用窗口的非工作区修饰(“关闭”菜单,“最小化”、“最大化”和“还原”按钮等)。 因此,需要提供自己的修饰。

任务栏显示

窗口的默认外观包括任务栏按钮,如下图中所示:

Screenshot that shows a window with a taskbar button.

一些类型的窗口没有任务栏按钮,例如消息框和对话框(请参阅对话框概述)。 设置 ShowInTaskbar 属性(默认为 true)可以控制是否显示窗口的任务栏按钮。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ShowInTaskbar="False">
</Window>

安全注意事项

Window 需要实例化 UnmanagedCode 安全权限。 对于从本地计算机安装并启动的应用程序,此权限在授予应用程序的权限集中。

但是,此权限不在授予使用 ClickOnce 以从 Internet 或本地 Intranet 区域启动的应用程序的权限集中。 因此,用户将收到 ClickOnce 安全警告,并需要将应用程序的权限集提升到完全信任级别。

另外,XBAP 在默认情况下无法显示窗口或对话框。 有关对独立应用程序安全注意事项的讨论,请参阅 WPF 安全策略 - 平台安全性

其他类型的窗口

NavigationWindow 是设计用于托管可导航内容的窗口。 有关详细信息,请参阅 导航概述

对话框是通常用来收集用户信息以完成某项功能的窗口。 例如,用户需要打开某个文件时,应用程序通常会显示“打开文件”对话框,以从用户那里获取文件名。 有关详细信息,请参阅对话框概述

另请参阅