WPF Windows 概述WPF Windows Overview

用户与 Windows Presentation Foundation (WPF) 独立应用程序通过 windows 进行交互。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 中提供的托管Windows Internet ExplorerWindows Internet ExplorerInstead, they are hosted in windows provided by Windows Internet ExplorerWindows 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 Build Engine (MSBuild)Microsoft build engine (MSBuild)来创建partial派生的类Window并且具有指定的名称x:Class属性。When the application is built, the existence of x:Class in the markup file causes Microsoft Build Engine (MSBuild)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到你的项目通过使用Microsoft Visual StudioMicrosoft Visual Studio,则Window通过使用标记和代码隐藏实现,并且包括必要的配置来创建作为标记和代码隐藏文件之间的关联此处所述。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

如何实现您的窗口确定如何将其配置为MSBuildMSBuildHow you implement your window determines how it is configured for MSBuildMSBuild. 使用同时定义窗口XAMLXAML标记和代码隐藏:For a window that is defined using both XAMLXAML markup and code-behind:

  • XAMLXAML 标记文件配置为MSBuildMSBuildPage项。markup files are configured as MSBuildMSBuildPage items.

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

这如下所示MSBuildMSBuild项目文件。This is shown in the following MSBuildMSBuild 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.

实例化窗口时,对它的引用自动添加到由一系列 windowsApplication对象 (请参阅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.

通过调用 window.show 而打开窗口

通过调用打开的窗口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 调用以模式方式打开诸如对话框窗口。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打开无模式方式; 在内部,打开窗口时通过调用其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:

  • 覆盖另 (除非其中一个窗口具有其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)Integrated Development Environment (IDE)应用程序可能打开属性窗口和工具窗口的典型行为是覆盖创建它们的窗口。For example, an 集成开发环境 (IDE)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.

  • 所有者窗口可以发现它拥有通过检查的值的所有 windows 其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.

  • 在窗口DeactivatedActivated按预期方式响应用户操作,随后会引发事件。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.

备注

第一次打开一个窗口,当LoadedContentRendered后才会引发事件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

当一个窗口关闭时,它会引发两个事件:ClosingClosedWhen 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. 下面的示例显示了处理的关键方面ClosingThe 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

Closing事件处理程序传递CancelEventArgs,它可以实现BooleanCancel属性设置为true可以阻止窗口关闭。The 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.

尽管可以通过在非客户端和客户端区域中提供的机制显式关闭窗口,窗口也可能隐式关闭应用程序的其他部分中的行为的结果或WindowsWindows,其中包括: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 WindowsWindows, 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,并LeftTop属性未设置,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. 一个窗口位于最顶层 z 顺序通过设置其Topmost属性设置为trueA 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.

MinWidthWidth,和MaxWidth用于管理的一个窗口可以在其生存期内,并且在下面的示例所示配置的宽度范围。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. 若要检测的当前宽度和高度,检查ActualWidthActualHeight分别。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.

使用窗口最大化状态扩展可以只能将一样大的最大大小为其MaxWidthMaxHeight,和SizeToContent属性规定。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.

备注

TopLeftWidth,和Height属性窗口的当前最大化或最小化窗口时,即使始终表示正常状态的值。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:

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

某些类型的窗口没有任务栏按钮,如消息框和对话框 (请参阅对话框概述)。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.

但是,此权限授予启动从 Internet 或本地 intranet 区域中使用的应用程序的权限集外ClickOnceClickOnceHowever, this falls outside the set of permissions granted to applications that are launched from the Internet or Local intranet zone using ClickOnceClickOnce. 因此,用户将收到ClickOnceClickOnce安全警告,需要提升的权限集为完全信任的应用程序。Consequently, users will receive a ClickOnceClickOnce 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