WPF Windows 概述WPF Windows Overview

用户通过 Windows 与 Windows Presentation Foundation (WPF) 独立应用程序交互。Users interact with Windows Presentation Foundation (WPF) standalone applications through windows. 窗口的主要用途是托管使数据可视化并使用户能够与数据交互的内容。The primary purpose of a window is to host content that visualizes data and enables users to interact with data. 独立WPFWPF应用程序Window使用类提供自己的窗口。Standalone WPFWPF applications provide their own windows by using the Window class. 本主题将Window介绍在独立的应用程序中创建和管理 windows 的基本原理。This topic introduces Window before covering the fundamentals of creating and managing windows in standalone applications.

备注

浏览器承载WPFWPF的应用程序XAML 浏览器应用程序 (XBAP)XAML browser applications (XBAPs) (包括可扩展应用程序标记语言 (XAML)Extensible Application Markup Language (XAML)和松散页面) 不提供其自己的窗口。Browser-hosted WPFWPF applications, including XAML 浏览器应用程序 (XBAP)XAML browser applications (XBAPs) and loose 可扩展应用程序标记语言 (XAML)Extensible Application Markup Language (XAML) pages, don't provide their own windows. 而是托管在 Windows Internet Explorer 提供的 windows 中。Instead, they are hosted in windows provided by Windows Internet Explorer. 请参阅WPF XAML 浏览器应用程序概述See WPF XAML Browser Applications Overview.

窗口类The Window Class

下图说明了窗口的组成部分:The following figure illustrates the constituent parts of a window:

显示窗口元素的屏幕截图。

窗口分为两个区域:非工作区和工作区。A window is divided into two areas: the non-client area and client area.

窗口的非工作区WPFWPF实现, 并包含大多数窗口所共有的窗口的各个部分, 包括以下各项:The non-client area of a window is implemented by WPFWPF and includes the parts of a window that are common to most windows, including the following:

  • 边框。A border.

  • 标题栏。A title bar.

  • 图标。An icon.

  • “最小化”、“最大化”和“还原”按钮。Minimize, Maximize, and Restore buttons.

  • “关闭”按钮。A Close button.

  • “系统”菜单,其中包含允许用户最小化、最大化、还原、移动和关闭窗口以及重设窗口大小的菜单项。A System menu with menu items that allow users to minimize, maximize, restore, move, resize, and close a window.

窗口的工作区是窗口非工作区内的区域, 开发人员使用它来添加特定于应用程序的内容, 例如菜单栏、工具栏和控件。The client area of a window is the area within a window's non-client area and is used by developers to add application-specific content, such as menu bars, tool bars, and controls.

WPFWPF中, 窗口Window由用于执行以下操作的类进行封装:In WPFWPF, a window is encapsulated by the Window class that you use to do the following:

  • 显示窗口。Display a window.

  • 配置窗口的大小、位置和外观。Configure the size, position, and appearance of a window.

  • 托管特定于应用程序的内容。Host application-specific content.

  • 管理窗口的生存期。Manage the lifetime of a window.

实现窗口Implementing a Window

典型窗口的实现同时包含外观和行为, 其中外观定义了窗口对用户和行为的外观, 定义了窗口与用户交互的方式。The implementation of a typical window comprises both appearance and behavior, where appearance defines how a window looks to users and behavior defines the way a window functions as users interact with it. WPFWPF中, 可以使用代码或XAMLXAML标记实现窗口的外观和行为。In WPFWPF, you can implement the appearance and behavior of a window using either code or XAMLXAML markup.

但一般情况下, 窗口的外观是使用XAMLXAML标记实现的, 其行为是使用代码隐藏实现的, 如下面的示例中所示。In general, however, the appearance of a window is implemented using XAMLXAML markup, and its behavior is implemented using code-behind, as shown in the following example.

<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

若要使XAMLXAML标记文件和代码隐藏文件协同工作, 需要满足以下要求:To enable a XAMLXAML markup file and code-behind file to work together, the following are required:

  • 在标记中, Window元素必须x:Class包含属性。In markup, the Window element must include the x:Class attribute. 生成应用程序x:Class后, 标记文件中存在会导致 Microsoft 生成引擎 (MSBuild) 创建一个partial派生自Window的类, 并x:Class具有由特性指定的名称。When the application is built, the existence of x:Class in the markup file causes Microsoft build engine (MSBuild) to create a partial class that derives from Window and has the name that is specified by the x:Class attribute. 这要求XMLXML XAMLXAML为架构 ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ) 添加命名空间声明。This requires the addition of an XMLXML namespace declaration for the XAMLXAML schema ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ). 生成partial的类InitializeComponent实现方法, 该方法用于注册事件并设置标记中实现的属性。The generated partial class implements the InitializeComponent method, which is called to register the events and set the properties that are implemented in markup.

  • 在代码隐藏中, 类必须是partial由标记中的x:Class特性指定的同名类, 并且必须派生自WindowIn code-behind, the class must be a partial class with the same name that is specified by the x:Class attribute in markup, and it must derive from Window. 这允许在生成应用程序时将代码隐藏文件与partial为标记文件生成的类相关联 (请参阅生成 WPF 应用程序)。This allows the code-behind file to be associated with the partial class that is generated for the markup file when the application is built (see Building a WPF Application).

  • 在代码隐藏中, Window该类必须实现InitializeComponent调用方法的构造函数。In code-behind, the Window class must implement a constructor that calls the InitializeComponent method. InitializeComponent由标记文件的生成partial类实现, 用于注册事件和设置在标记中定义的属性。InitializeComponent is implemented by the markup file's generated partial class to register events and set properties that are defined in markup.

备注

使用Window Window将新添加到项目时, 将使用标记和代码隐藏来实现, 并包含必要的配置以创建标记和代码隐藏文件之间的关联。 Microsoft Visual StudioMicrosoft Visual Studio此处所述。When you add a new Window to your project by using Microsoft Visual StudioMicrosoft Visual Studio, the Window is implemented using both markup and code-behind, and includes the necessary configuration to create the association between the markup and code-behind files as described here.

通过此配置, 你可以专注于定义标记中XAMLXAML窗口的外观并在代码隐藏中实现其行为。With this configuration in place, you can focus on defining the appearance of the window in XAMLXAML markup and implementing its behavior in code-behind. 下面的示例演示了一个窗口, 其中包含一个按钮XAMLXAML , 在标记中实现并在代码隐藏中Click实现了该按钮事件的事件处理程序。The following example shows a window with a button, implemented in XAMLXAML markup, and an event handler for the button's Click event, implemented in code-behind.

<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 配置窗口定义Configuring a Window Definition for MSBuild

如何实现窗口将决定如何为 MSBuild 配置它。How you implement your window determines how it is configured for MSBuild. 对于使用XAMLXAML标记和代码隐藏定义的窗口:For a window that is defined using both XAMLXAML markup and code-behind:

  • XAML 标记文件配置为 MSBuild Page项。XAML markup files are configured as MSBuild Page items.

  • 代码隐藏文件配置为 MSBuild Compile项。Code-behind files are configured as MSBuild Compile items.

下面的 MSBuild 项目文件中显示了这种情况。This is shown in the following MSBuild project file.

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

有关生成WPFWPF应用程序的信息, 请参阅生成 WPF 应用程序For information about building WPFWPF applications, see Building a WPF Application.

窗口生存期Window Lifetime

与所有类一样,窗口也有生存期,开始于首次实例化窗口,在这之后将打开、激活、停用直至最终关闭窗口。As with any class, a window has a lifetime that begins when it is first instantiated, after which it is opened, activated and deactivated, and eventually closed.

打开窗口Opening a Window

若要打开窗口,首先要创建窗口实例,下面的示例演示此操作。To open a window, you first create an instance of it, which is demonstrated in the following example.

<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引发事件时发生。In this example, the MarkupAndCodeBehindWindow is instantiated when the application starts, which occurs when the Startup event is raised.

在实例化窗口时, 对它的引用会自动添加到由该Application对象管理的窗口的列表中 (请参见Application.Windows)。When a window is instantiated, a reference to it is automatically added to a list of windows that is managed by the Application object (see Application.Windows). 此外, 默认情况下, 第一个要实例化的窗口是由Application设置为主应用程序窗口 ( Application.MainWindow请参阅)。Additionally, the first window to be instantiated is, by default, set by Application as the main application window (see Application.MainWindow).

最后, 通过调用Show方法打开该窗口; 结果如下图所示。The window is finally opened by calling the Show method; the result is shown in the following figure.

通过调用窗口打开的窗口。显示

通过调用Show打开的窗口是一个无模式窗口, 这意味着应用程序以允许用户在同一应用程序中激活其他窗口的模式操作。A window that is opened by calling Show is a modeless window, which means that the application operates in a mode that allows users to activate other windows in the same application.

备注

ShowDialog调用以模式打开 windows, 如对话框。ShowDialog is called to open windows such as dialog boxes modally. 有关详细信息, 请参阅对话框概述See Dialog Boxes Overview for more information.

调用Show时, 窗口将执行初始化工作, 并显示该工作以建立允许它接收用户输入的基础结构。When Show is called, a window performs initialization work before it is shown to establish infrastructure that allows it to receive user input. 初始化窗口时, SourceInitialized将引发事件, 并显示窗口。When the window is initialized, the SourceInitialized event is raised and the window is shown.

作为快捷方式, StartupUri可以将设置为指定应用程序启动时自动打开的第一个窗口。As a shortcut, StartupUri can be set to specify the first window that is opened automatically when an application starts.

<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所指定的窗口将在 modelessly 中打开。通过调用其Show方法, 打开窗口。When the application starts, the window specified by the value of StartupUri is opened modelessly; internally, the window is opened by calling its Show method.

窗口所有权Window Ownership

使用Show方法打开的窗口与创建它的窗口不具有隐式关系; 用户可以与任何一个窗口独立交互, 这意味着, 这两个窗口都可以执行以下操作:A window that is opened by using the Show method does not have an implicit relationship with the window that created it; users can interact with either window independently of the other, which means that either window can do the following:

  • 覆盖其他 (除非其中一个 windows Topmost的属性设置为true)。Cover the other (unless one of the windows has its Topmost property set to true).

  • 在不影响另一个窗口的情况下最小化、最大化和还原。Be minimized, maximized, and restored without affecting the other.

某些窗口要求与打开它们的窗口保持某种关系。Some windows require a relationship with the window that opens them. 例如, 集成开发环境 (IDE) 应用程序可以打开属性窗口和工具窗口, 其典型行为是涵盖创建它们的窗口。For example, an Integrated Development Environment (IDE) application may open property windows and tool windows whose typical behavior is to cover the window that creates them. 此外,此类窗口应始终与创建它们的窗口一起关闭、最小化、最大化和还原。Furthermore, such windows should always close, minimize, maximize, and restore in concert with the window that created them. 这种关系可通过使一个窗口成为一个窗口而建立, 通过设置Owner 拥有的窗口的属性和对所有者窗口的引用来实现。Such a relationship can be established by making one window own another, and is achieved by setting the Owner property of the owned window with a reference to the owner window. 这在下面的示例中显示。This is shown in the following example.

// 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()

建立所有权后:After ownership is established:

  • 拥有的窗口可以通过检查其Owner属性的值引用其所有者窗口。The owned window can reference its owner window by inspecting the value of its Owner property.

  • 所有者窗口可以通过检查其OwnedWindows属性的值来发现其拥有的所有窗口。The owner window can discover all the windows it owns by inspecting the value of its OwnedWindows property.

防止窗口激活Preventing Window Activation

在某些情况下, windows 不应在显示时激活, 如 Internet messenger 样式应用程序的对话窗口或电子邮件应用程序的通知窗口。There are scenarios where windows should not be activated when shown, such as conversation windows of an Internet messenger-style application or notification windows of an email application.

如果你的应用程序具有在显示时不应激活的窗口, 则可ShowActivated在第false一次调用Show方法之前, 将其属性设置为。If your application has a window that shouldn't be activated when shown, you can set its ShowActivated property to false before calling the Show method for the first time. 结果是:As a consequence:

  • 不会激活窗口。The window is not activated.

  • 不引发窗口Activated的事件。The window's Activated event is not raised.

  • 当前激活的窗口保持激活状态。The currently activated window remains activated.

但是,只要用户通过单击工作区或非工作区激活了窗口,窗口就会变为激活状态。The window will become activated, however, as soon as the user activates it by clicking either the client or non-client area. 这种情况下:In this case:

  • 已激活窗口。The window is activated.

  • 引发窗口的Activated事件。The window's Activated event is raised.

  • 停用之前激活的窗口。The previously activated window is deactivated.

  • 随后会按Deactivated预期Activated方式引发窗口和事件以响应用户操作。The window's Deactivated and Activated events are subsequently raised as expected in response to user actions.

窗口激活Window Activation

第一次打开窗口时, 它将成为活动窗口 (除非显示时显示ShowActivated "设置为false")。When a window is first opened, it becomes the active window (unless it is shown with ShowActivated set to false). 活动窗口是当前正在捕获用户输入的窗口, 例如键击和鼠标单击。The active window is the window that is currently capturing user input, such as key strokes and mouse clicks. 当窗口处于活动状态时, 它会Activated引发事件。When a window becomes active, it raises the Activated event.

备注

首次打开窗口时, Loaded仅在引发ContentRendered Activated事件后引发和事件。When a window is first opened, the Loaded and ContentRendered events are raised only after the Activated event is raised. 考虑到这一点, 当引发时ContentRendered , 可以有效地将窗口视为已打开。With this in mind, a window can effectively be considered opened when ContentRendered is raised.

某个窗口成为活动窗口后,用户可以在同一应用程序内激活其他窗口,或者激活其他应用程序。After a window becomes active, a user can activate another window in the same application, or activate another application. 发生这种情况时, 将停用当前处于活动状态Deactivated的窗口, 并引发事件。When that happens, the currently active window becomes deactivated and raises the Deactivated event. 同样, 当用户选择当前已停用的窗口时, 该窗口将再次Activated变为活动状态并引发。Likewise, when the user selects a currently deactivated window, the window becomes active again and Activated is raised.

处理ActivatedDeactivated的一个常见原因是启用和禁用只能在窗口处于活动状态时运行的功能。One common reason to handle Activated and Deactivated is to enable and disable functionality that can only run when a window is active. 例如,一些窗口显示需要用户持续输入或关注的交互式内容,这些内容包括游戏和视频播放器。For example, some windows display interactive content that requires constant user input or attention, including games and video players. 下面的示例是一个简化的视频播放器, 演示如何处理ActivatedDeactivated实现此行为。The following example is a simplified video player that demonstrates how to handle Activated and Deactivated to implement this behavior.

<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
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

停用某个窗口后,其他类型的应用程序可能仍会在后台运行代码。Other types of applications may still run code in the background when a window is deactivated. 例如,在用户使用其他应用程序时,邮件客户端可能会继续轮询邮件服务器。For example, a mail client may continue polling the mail server while the user is using other applications. 类似的应用程序在主窗口停用时,通常将提供不同或其他的行为。Applications like these often provide different or additional behavior while the main window is deactivated. 对于邮件程序,这可能意味着将新邮件项添加到收件箱和将通知图标添加到系统任务栏。With respect to the mail program, this may mean both adding the new mail item to the inbox and adding a notification icon to the system tray. 仅当邮件窗口不处于活动状态时才显示通知图标, 可以通过检查IsActive属性来确定。A notification icon need only be displayed when the mail window isn't active, which can be determined by inspecting the IsActive property.

如果后台任务已完成, 则窗口可能需要通过调用Activate方法更紧急地通知用户。If a background task completes, a window may want to notify the user more urgently by calling Activate method. 如果用户与调用时Activate激活的其他应用程序交互, 则窗口的任务栏按钮会闪烁。If the user is interacting with another application activated when Activate is called, the window's taskbar button flashes. 如果用户与当前应用程序交互, 则调用Activate会将窗口置于前台。If a user is interacting with the current application, calling Activate will bring the window to the foreground.

备注

您可以使用Application.ActivatedApplication.Deactivated事件处理应用程序范围的激活。You can handle application-scope activation using the Application.Activated and Application.Deactivated events.

关闭窗口Closing a Window

窗口的生存期在用户关闭它时终止。The life of a window starts coming to an end when a user closes it. 可以使用非工作区中的元素关闭窗口,这些元素包括:A window can be closed by using elements in the non-client area, including the following:

  • 系统菜单的关闭项。The Close item of the System menu.

  • 按 ALT+F4。Pressing ALT+F4.

  • 按 "关闭" 按钮。Pressing the Close button.

可以向工作区提供其他关闭窗口的机制,较为常见的机制包括:You can provide additional mechanisms to the client area to close a window, the more common of which include the following:

  • "文件" 菜单中的 "退出" 项, 通常用于主应用程序窗口。An Exit item in the File menu, typically for main application windows.

  • "文件" 菜单中的 "关闭" 项, 通常在辅助应用程序窗口中。A Close item in the File menu, typically on a secondary application window.

  • "取消" 按钮, 通常位于模式对话框中。A Cancel button, typically on a modal dialog box.

  • "关闭" 按钮, 通常位于无模式对话框中。A Close button, typically on a modeless dialog box.

若要关闭窗口以响应其中一种自定义机制, 需要调用Close方法。To close a window in response to one of these custom mechanisms, you need to call the Close method. 下面的示例通过选择 "文件" 菜单上的 "退出" 来实现关闭窗口的功能。The following example implements the ability to close a window by choosing the Exit on the File menu.

<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

当窗口关闭时, 它将引发两个Closing事件Closed: 和。When a window closes, it raises two events: Closing and Closed.

Closing在窗口关闭前引发, 并提供一种机制, 可通过该机制阻止窗口关闭。Closing is raised before the window closes, and it provides a mechanism by which window closure can be prevented. 阻止窗口关闭的一个常见原因是窗口内容包含修改的数据。One common reason to prevent window closure is if window content contains modified data. 在这种情况下Closing , 可以处理事件以确定数据是否处于脏状态, 如果是, 则要求用户是否继续关闭窗口而不保存数据或取消关闭窗口。In this situation, the Closing event can be handled to determine whether data is dirty and, if so, to ask the user whether to either continue closing the window without saving the data or to cancel window closure. 下面的示例演示了处理Closing的关键方面。The following example shows the key aspects of handling 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

Boolean true Cancel向事件处理程序CancelEventArgs传递, 该事件处理程序实现了设置为的属性, 以防止窗口关闭。 ClosingThe Closing event handler is passed a CancelEventArgs, which implements the BooleanCancel property that you set to true to prevent a window from closing.

如果Closing未处理, 或者处理但未取消, 则窗口将关闭。If Closing is not handled, or it is handled but not canceled, the window will close. 在窗口实际关闭之前, Closed将引发。Just before a window actually closes, Closed is raised. 此时,无法阻止窗口关闭。At this point, a window cannot be prevented from closing.

备注

在主应用程序窗口关闭 (请参阅MainWindow) 或最后一个窗口关闭时, 可以将应用程序配置为自动关闭。An application can be configured to shut down automatically when either the main application window closes (see MainWindow) or the last window closes. 有关详细信息,请参阅 ShutdownModeFor details, see ShutdownMode.

尽管可以通过非客户端和客户端区域中提供的机制显式关闭窗口, 但也可以通过应用程序或窗口的其他部分中的行为来隐式关闭窗口, 其中包括:While a window can be explicitly closed through mechanisms provided in the non-client and client areas, a window can also be implicitly closed as a result of behavior in other parts of the application or Windows, including the following:

备注

窗口在关闭后无法重新打开。A window cannot be reopened after it is closed.

窗口生存期事件Window Lifetime Events

下图显示了窗口生存期内的主体事件的顺序:The following illustration shows the sequence of the principal events in the lifetime of a window:

在窗口生存期内显示事件的关系图。

下图显示了在未激活的情况下显示的窗口生存期内的主体事件的顺序 (ShowActivated在显示窗口之前设置为false ):The following illustration shows the sequence of the principal events in the lifetime of a window that is shown without activation (ShowActivated is set to false before the window is shown):

在不激活的情况下显示窗口生存期内的事件的关系图。

窗口位置Window Location

当窗口打开时,它在相对于桌面的 x 和 y 维度中有一个位置。While a window is open, it has a location in the x and y dimensions relative to the desktop. 可以通过分别检查LeftTop属性来确定此位置。This location can be determined by inspecting the Left and Top properties, respectively. 设置这些属性可以更改窗口的位置。You can set these properties to change the location of the window.

你还可以通过使用以下Window WindowStartupLocation枚举值之一WindowStartupLocation设置属性, 来指定第一次出现的起始位置:You can also specify the initial location of a Window when it first appears by setting the WindowStartupLocation property with one of the following WindowStartupLocation enumeration values:

如果将启动位置指定Manual为, Left并且未设置和Top属性, Window将要求 Windows 提供要显示在中的位置。If the startup location is specified as Manual, and the Left and Top properties have not been set, Window will ask Windows for a location to appear in.

最顶层窗口和 Z 顺序Topmost Windows and Z-Order

除了有 x 和 y 位置外,窗口还在 z 维度中有一个位置,该位置确定窗口相对于其他窗口的垂直位置。Besides having an x and y location, a window also has a location in the z dimension, which determines its vertical position with respect to other windows. 它称为窗口的 z 顺序,并且有两种类型:正常 z 顺序和最顶层 z 顺序。This is known as the window's z-order, and there are two types: normal z-order and topmost z-order. 处于正常 z 顺序中的窗口的位置取决于它当前是否处于活动状态。The location of a window in the normal z-order is determined by whether it is currently active or not. 默认情况下,窗口位于正常 z 顺序中。By default, a window is located in the normal z-order. 最顶层 z 顺序中的窗口位置也取决于它当前是否处于活动状态。The location of a window in the topmost z-order is also determined by whether it is currently active or not. 此外,最顶层 z 顺序中的窗口始终位于正常 z 顺序中的窗口之上。Furthermore, windows in the topmost z-order are always located above windows in the normal z-order. 窗口通过将其Topmost属性设置为true, 位于最顶层 z 顺序中。A window is located in the topmost z-order by setting its Topmost property to true.

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

在每个 z 顺序中,当前的活动窗口显示在同一 z 顺序中所有其他窗口之上。Within each z-order, the currently active window appears above all other windows in the same z-order.

窗口大小Window Size

除了拥有桌面位置, 窗口的大小由多个属性确定, 其中包括各种宽度和高度属性以及SizeToContentBesides having a desktop location, a window has a size that is determined by several properties, including the various width and height properties and SizeToContent.

MinWidthWidthMaxWidth用于管理窗口在其生存期内可以具有的宽度范围, 并按以下示例所示进行配置。MinWidth, Width, and MaxWidth are used to manage the range of widths that a window can have during its lifetime, and are configured as shown in the following example.

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

窗口高度由MinHeightHeight、和MaxHeight进行管理, 如以下示例中所示。Window height is managed by MinHeight, Height, and MaxHeight, and are configured as shown in the following example.

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

由于各种宽度值和高度值各自指定了一个范围,所以大小可调整大小的窗口的宽度和高度可以是相应维度中指定范围内的任何值。Because the various width values and height values each specify a range, it is possible for the width and height of a resizable window to be anywhere within the specified range for the respective dimension. 若要检测其当前的宽度和高度ActualWidth , ActualHeight请分别检查和。To detect its current width and height, inspect ActualWidth and ActualHeight, respectively.

如果希望窗口的宽度和高度与窗口内容的大小相符, 则可以使用SizeToContent属性, 该属性具有以下各值:If you'd like the width and height of your window to have a size that fits to the size of the window's content, you can use the SizeToContent property, which has the following values:

以下示例显示了一个窗口,它在第一次显示时即自动调整垂直方向和水平方向上的大小以适应内容。The following example shows a window that automatically sizes to fit its content, both vertically and horizontally, when first shown.

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

下面的示例演示如何在代码中SizeToContent设置属性, 以指定如何调整窗口大小以适应其内容。The following example shows how to set the SizeToContent property in code to specify how a window resizes to fit its content .


// 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

大小调整属性的优先级顺序Order of Precedence for Sizing Properties

从根本上说,窗口的各种大小属性可以结合使用,以定义可调整大小的窗口的宽度和高度范围。Essentially, the various sizes properties of a window combine to define the range of width and height for a resizable window. 若要确保保持有效的范围, Window请使用以下优先级顺序计算大小属性的值。To ensure a valid range is maintained, Window evaluates the values of the size properties using the following orders of precedence.

对于高度属性:For Height Properties:

  1. FrameworkElement.MinHeight

  2. FrameworkElement.MaxHeight

  3. SizeToContent.Height/SizeToContent.WidthAndHeight

  4. FrameworkElement.Height

对于宽度属性:For Width Properties:

  1. FrameworkElement.MinWidth

  2. FrameworkElement.MaxWidth

  3. SizeToContent.Width/SizeToContent.WidthAndHeight

  4. FrameworkElement.Width

优先级顺序还可以确定窗口最大化时的窗口大小, 该大小是使用WindowState属性管理的。The order of precedence can also determine the size of a window when it is maximized, which is managed with the WindowState property.

窗口状态Window State

可调整大小的窗口在生存期中拥有三种状态:正常、最小化和最大化。During the lifetime of a resizable window, it can have three states: normal, minimized, and maximized. 处于正常状态的窗口是窗口的默认状态。A window with a normal state is the default state of a window. 这种状态下的窗口允许用户使用重设大小手柄或边框移动窗口和重设其大小(前提是大小可以重设)。A window with this state allows a user to move and resize it by using a resize grip or the border, if it is resizable.

如果ShowInTaskbar设置为true, 则具有最小化状态的窗口将折叠到其任务栏按钮; 否则, 它将折叠为可能的最小大小, 并将自身重定位到桌面左下角。A window with a minimized state collapses to its task bar button if ShowInTaskbar is set to true; otherwise, it collapses to the smallest possible size it can be and relocates itself to the bottom-left corner of the desktop. 虽然不在任务栏显示的最小化窗口可以在桌面上四处拖动,但这两种类型的最小化窗口都不可以使用边框或重设大小手柄重设窗口大小。Neither type of minimized window can be resized using a border or resize grip, although a minimized window that isn't shown in the task bar can be dragged around the desktop.

处于最大化状态的窗口将扩展为它的最大大小, 这将只是其MaxWidthMaxHeightSizeToContent属性所规定的大小。A window with a maximized state expands to the maximum size it can be, which will only be as large as its MaxWidth, MaxHeight, and SizeToContent properties dictate. 与最小化窗口一样,最大化窗口无法使用重设大小手柄或通过拖动边框来重设大小。Like a minimized window, a maximized window cannot be resized by using a resize grip or by dragging the border.

备注

即使窗口当前已Top最大化Width或最Height小化, 窗口的、 Left、和属性的值也始终表示正常状态的值。The values of the Top, Left, Width, and Height properties of a window always represent the values for the normal state, even when the window is currently maximized or minimized.

窗口的状态可以通过设置其WindowState属性来配置, 该属性可以具有以下WindowState枚举值之一:The state of a window can be configured by setting its WindowState property, which can have one of the following WindowState enumeration values:

以下示例显示如何创建在打开时最大化显示的窗口。The following example shows how to create a window that is shown as maximized when it opens.

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

通常, 应将设置WindowState为配置窗口的初始状态。In general, you should set WindowState to configure the initial state of a window. 显示可调整大小的窗口后,用户可以按窗口标题栏上的“最小化”、“最大化”和“还原”按钮来更改窗口状态。Once a resizable window is shown, users can press the minimize, maximize, and restore buttons on the window's title bar to change the window state.

窗口外观Window Appearance

通过将特定于窗口的内容(例如按钮、标签和文本框)添加到窗口的工作区可以更改它的外观。You change the appearance of the client area of a window by adding window-specific content to it, such as buttons, labels, and text boxes. 若要配置非工作区, Window提供了几个属性, 其中包括Icon设置窗口图标以及Title设置其标题。To configure the non-client area, Window provides several properties, which include Icon to set a window's icon and Title to set its title.

还可以通过配置窗口的重设大小模式、窗口样式,以及窗口是否显示为桌面任务栏中的按钮,更改非工作区边框的外观和行为。You can also change the appearance and behavior of non-client area border by configuring a window's resize mode, window style, and whether it appears as a button in the desktop task bar.

重设大小模式Resize Mode

WindowStyle根据属性, 您可以控制用户如何 (以及用户) 如何调整窗口的大小。Depending on the WindowStyle property, you can control how (and if) users can resize the window. 窗口样式的选择会影响用户是否可以通过使用鼠标拖动边框来调整窗口的大小, 无论是在非工作区显示 "最小化"、"最大化" 和 "重设大小" 按钮,能够.The choice of window style affects whether a user can resize the window by dragging its border with the mouse, whether the Minimize, Maximize, and Resize buttons appear on the non-client area, and, if they do appear, whether they are enabled.

您可以通过设置ResizeMode窗口的属性来配置窗口调整大小的方式, 可以是下列ResizeMode枚举值之一:You can configure how a window resizes by setting its ResizeMode property, which can be one of the following ResizeMode enumeration values:

WindowStyle一样, 窗口的重设大小模式不太可能在其生存期内发生更改, 这意味着你很可能会从标记XAMLXAML中进行设置。As with WindowStyle, the resize mode of a window is unlikely to change during its lifetime, which means that you'll most likely set it from XAMLXAML markup.

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

请注意, 可以通过检查WindowState属性来检测窗口是最大化、最小化还是已还原。Note that you can detect whether a window is maximized, minimized, or restored by inspecting the WindowState property.

窗口样式Window Style

从窗口非工作区公开的边框适用于大多数应用程序。The border that is exposed from the non-client area of a window is suitable for most applications. 但是,有时候会需要不同类型的边框,或者根本不需要边框,具体取决于窗口类型。However, there are circumstances where different types of borders are needed, or no borders are needed at all, depending on the type of window.

若要控制窗口的边框类型, 请将其WindowStyle属性设置为以下WindowStyle枚举值之一:To control what type of border a window gets, you set its WindowStyle property with one of the following values of the WindowStyle enumeration:

下图演示了这些窗口样式的效果:The effect of these window styles are illustrated in the following figure:

窗口边框样式的插图。

您可以WindowStyle XAMLXAML使用标记或代码进行设置; 因为在窗口生存期内不太可能更改, 因此您最有可能使用XAMLXAML标记对其进行配置。You can set WindowStyle using either XAMLXAML markup or code; because it is unlikely to change during the lifetime of a window, you will most likely configure it using XAMLXAML markup.

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

非矩形窗口样式Non-Rectangular Window Style

在某些情况下, WindowStyle允许您使用的边框样式并不够。There are also situations where the border styles that WindowStyle allows you to have are not sufficient. 例如, 你可能希望使用非矩形边框 (如Microsoft Windows Media PlayerMicrosoft Windows Media Player使用) 创建应用程序。For example, you may want to create an application with a non-rectangular border, like Microsoft Windows Media PlayerMicrosoft Windows Media Player uses.

例如, 请看下图中显示的语音气泡窗口:For example, consider the speech bubble window shown in the following figure:

显示 "拖动" 的语音气泡窗口。

可以通过将WindowStyle属性设置为None, 并使用Window具有透明度的特殊支持来创建此类型的窗口。This type of window can be created by setting the WindowStyle property to None, and by using special support that Window has for transparency.

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

多个值组合起来可以指示窗口呈现完全透明的效果。This combination of values instructs the window to render completely transparent. 在这种状态下,无法使用窗口的非工作区修饰(“关闭”菜单,“最小化”、“最大化”和“还原”按钮等)。In this state, the window's non-client area adornments (the Close menu, Minimize, Maximize, and Restore buttons, and so on) cannot be used. 因此,需要提供自己的修饰。Consequently, you need to provide your own.

任务栏显示Task Bar Presence

窗口的默认外观包含一个任务栏按钮, 如下图中所示:The default appearance of a window includes a taskbar button, like the one shown in the following figure:

显示具有任务栏按钮的窗口的屏幕截图。

某些类型的 windows 没有任务栏按钮, 如消息框和对话框 (请参阅对话框概述)。Some types of windows don't have a task bar button, such as message boxes and dialog boxes (see Dialog Boxes Overview). 您可以通过设置ShowInTaskbar属性 (true默认情况下) 来控制是否显示窗口的任务栏按钮。You can control whether the task bar button for a window is shown by setting the ShowInTaskbar property (true by default).

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

安全注意事项Security Considerations

Window需要UnmanagedCode实例化安全权限。Window requires UnmanagedCode security permission to be instantiated. 对于从本地计算机安装并启动的应用程序,此权限在授予应用程序的权限集中。For applications installed on and launched from the local machine, this falls within the set of permissions that are granted to the application.

但是, 这超出了向使用 ClickOnce 从 Internet 或本地 intranet 区域启动的应用程序授予的权限集。However, this falls outside the set of permissions granted to applications that are launched from the Internet or Local intranet zone using ClickOnce. 因此, 用户将收到 ClickOnce 安全警告, 需要将应用程序的权限集提升到完全信任。Consequently, users will receive a ClickOnce security warning and will need to elevate the permission set for the application to full trust.

此外, XBAPXBAPs默认情况下无法显示窗口或对话框。Additionally, XBAPXBAPs cannot show windows or dialog boxes by default. 有关独立应用程序安全注意事项的讨论, 请参阅WPF 安全策略-平台安全性For a discussion on standalone application security considerations, see WPF Security Strategy - Platform Security.

其他类型的窗口Other Types of Windows

NavigationWindow是旨在承载可导航内容的窗口。NavigationWindow is a window that is designed to host navigable content. 有关详细信息, 请参阅导航概述For more information, see Navigation Overview).

对话框是通常用来收集用户信息以完成某项功能的窗口。Dialog boxes are windows that are often used to gather information from a user to complete a function. 例如, 当用户要打开文件时, 应用程序通常会显示 "打开文件" 对话框以获取用户的文件名。For example, when a user wants to open a file, the Open File dialog box is usually displayed by an application to get the file name from the user. 有关详细信息,请参阅对话框概述For more information, see Dialog Boxes Overview.

请参阅See also