Condividi tramite


Windows Presentation Foundation Windows Overview

Users interact with Windows Presentation Foundation (WPF) standalone applications through windows, whose primary purpose is to host content that visualizes data and enables users to interact with data.

This topic contains the following sections.

  • The Window Class
  • Implementing a Window
  • Configuring a Window Definition for MSBuild
  • Window Lifetime
  • Window Location
  • Window Size
  • Order of Precedence for Sizing Properties
  • Window State
  • Window Appearance
  • Security Considerations
  • Related Topics

The Window Class

The following figure illustrates the elements of a typical window.

Window elements

A window is divided into two areas: the non-client area and client area.

The non-client area of a window is implemented by WPF, and includes the elements 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, which provides menu items to minimize, maximize, restore, moves, resize, and close a window.

The client area of a window is the area within the non-client area of a window, and is used by developers to add window-specific content.

In WPF, a window is encapsulated by the Window class, which allows you to:

  • Configure the size, position, and appearance of a window.

  • Host content within a window.

  • Display a window.

  • Manage a windows lifetime.

Message boxes and dialog boxes are other types of windows that are discussed in Dialog Boxes Overview. Furthermore, the NavigationWindow is a special type of window that derives from Window and extends it with support for displaying and navigable content (see Navigation Overview).

Implementing a Window

An implementation of a window encompasses appearance and behavior. Appearance is the way the window looks, while behavior is the way in which a window functions. In WPF, you can implement the appearance and behavior of a window using either code or markup, or both. However, markup and code-behind is the most common.

Defining a Window in Markup and Code-Behind

Implementing a window by using both markup and code-behind is the best of both worlds; you can utilize the expressiveness of XAML to define your appearance, while using code to implement the behavior.

The following example shows a window that is implemented using both markup and code.

<Window
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="MarkupAndCodeBehindWindow">
  <!-- Client Area (for content) -->
</Window>
using System.Windows;
public partial class MarkupAndCodeBehindWindow : Window
{
    public MarkupAndCodeBehindWindow()
    {
        InitializeComponent();
    }
}

To enable a markup file and code-behind file to work together, the following is required:

  • In markup, the Window element must include the x:Class attribute, which instructs MSBuild to create a partial class for the markup file when the project is built with the name specified by the x:Class attribute. This requires the addition of an XML namespace declaration for the XAML schema (xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"). The partial generated partial class implements InitializeComponent, which is called to register the events and set the properties that are implemented in markup.

  • In code-behind, the class must be a partial class with the same name that is specified by the x:Class attribute in markup, and needs to derive from Window. This allows the code-behind file to be associated with the partial class that is generated for the markup file when it is built (see Building a Windows Presentation Foundation Application).

  • In code-behind, the class must implement a constructor that calls the InitializeComponent method, otherwise the markup will not be applied.

NoteNote:

When you add a new window to your project using Microsoft 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.

The following example shows how to use markup and code-behind to set the title of the window, declare a button using XAML, and to handle the Click event in code-behind.

<Window 
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MarkupAndCodeBehindWindow"
  Title="WindowsOverviewSnippetsCSharp"
  Height="800" 
  Width="600">
    <!-- Client Area (for content) -->
    <Button Click="button_Click">Window Content</Button>
</Window>
using System.Windows;
public partial class MarkupAndCodeBehindWindow : Window
{
    public MarkupAndCodeBehindWindow()
    {
        InitializeComponent();
    }

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

Configuring a Window Definition for MSBuild

How you define your window determines how it is configured for Microsoft build engine (MSBuild). For a window that is defined using both markup and code-behind:

  • The markup file needs to be configured as an MSBuild Page item.

  • The code-behind file needs to be configures as an MSBuild Compile item.

This is shown in the following example:

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

Here, the code-behind file is configured as an MSBuild Compile item. Furthermore, the code-behind file has the same file name as the markup file, with an additional language-specific suffix (.cs or .vb). The suffix is not required although Microsoft Visual Studio uses this convention by default.

NoteNote:

For in-depth coverage of building WPF applications, see Building a Windows Presentation Foundation Application.

Window Lifetime

Once the window has been defined and configured for MSBuild, you can show it from your application. As with any class, a window has a lifetime that begins when it is first instantiated, after which it is shown, activated and deactivated, before being finally closed.

Opening a Window

To open a window, you first create an instance of it, as demonstrated by the following example.

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

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

In this example, the MarkupAndCodeBehindWindow is instantiated when the application starts (see Application Management Overview).

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 System.Windows.Application.Windows). Furthermore, the first window to be instantiated is, by default, set by Application as the main application window (see System.Windows.Application.MainWindow).

The window is finally opened by calling the Show method, which yields the following figure.

A window that is opened by calling Show is a modeless window, which means that the application operates in mode that allows users to activate other windows in the same application. Window also implements the ShowDialog method, which is used to open a modal window. The most common type of modal window is a dialog box, which is discussed further in Dialog Boxes Overview.

As a shortcut, and as long as the window implementation includes markup, you can declaratively configure your application definition to open the main window automatically by setting the StartupUri property in markup:

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

When the application starts, this markup causes the MarkupAndCodeBehindWindow window to be shown modelessly by calling its Show method.

When Show is called, a window needs to perform some initialization work before it is actually shown. The focus of the initialization is to establish the infrastructure that allows it to receive user input. When initialization is complete, the SourceInitialized event is raised and the window is shown.

Window Ownership

When a window is opened by calling Show, it has no knowledge of, or relationship with, the window that created it; users will be able to interact with each window independently of the other. This means that either window can:

  • Cover the other (unless one of the windows has its Topmost property set to true).

  • Be minimized, maximized, and restored without affecting the other.

For some applications, an opened window needs to have a tighter relationship with the window that opens it. For example, an Integrated Development Environment (IDE) application may open windows like property and tool windows, which should always cover the window that creates them, and should always close, minimize, maximize, and restore in concert with the window that created them.

You can implement this behavior by making one window own another window, a relationship that is established by setting the Owner property:

using System.Windows;
public partial class OwnerWindow : System.Windows.Window
{
    public OwnerWindow()
    {
        InitializeComponent();
    }

    void OpenOwnedWindow()
    {
        // NOTE: Owner must be shown before it can own another window
        // Create new owned window and show it
        OwnedWindow ownedWindow = new OwnedWindow();
        ownedWindow.Owner = this;
        ownedWindow.Show();
    }
}

Once ownership is established, the owned window can reference its owner window through the Owner property. The owner window can discover all the windows it owns by enumerating the OwnedWindows property.

Window Activation

When a window is first opened, it becomes the foreground window, which means that it is the window that is currently capturing user input such as key strokes and mouse clicks; this window is also known as the active window. A window becomes the active window when it is opened for the first time, or when a user selects it. In both cases, the window raises the Activated event.

NoteNote:

When a window is first opened, the Loaded, and ContentRendered events are raised only after the Activated event is raised. Consequently, a window is considered to have opened only when ContentRendered is raised.

After a window becomes active, a user can activate another window in the same application, or activate another application. When that happens, the currently active window becomes deactivated and raises the Deactivated event:

One reason to handle Activated and Deactivated is to enable and disable functionality that can only run when a window is active, for example windows that require constant user input or attention such as games or video players.

The following example shows how to handle Activated and Deactivated to implement this behavior:

<Window
    x:Class="CustomMediaPlayerWindow"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Media Player"
    Activated="window_Activated"
    Deactivated="window_Deactivated">
  ...
</Window>
using System.Windows;
public partial class CustomMediaPlayerWindow : Window
{
    ...
    bool isMediaElementPlaying;
    void window_Activated(object sender, EventArgs e)
    {
        // Recommence playing media if window is activated
        If (this.isMediaElementPlaying) this.mediaElement.Play();
    }
    void window_Deactivated(object sender, EventArgs e)
    {
        // Pause playing if media is being played and window is deactivated
        if (this.isMediaElementPlaying) this.mediaElement.Pause();
    }
}
NoteNote:

See Window Activation and Deactivation Sample for the complete sample.

Sometimes, a window may still be running code, even if it is not the active window. 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 not only adding the new mail to the inbox, but may also mean adding an icon to the system tray to notify the user. To determine if it needs to perform this behavior, it can detect whether a window is activated or not by inspecting the IsActive property.

Alternatively, a window may want to become the active window, particularly if it needs to notify the user more urgently. You can allow it to by calling the Activate method.

NoteNote:

You can handle application-scope activation using the System.Windows.Application.Activated and System.Windows.Application.Deactivated events.

Closing a Window

When a user is finished with a window, they will want to close it. A window can be closed by using elements in the non-client area, including the following:

  • The Close item of the System menu.

  • Pressing ALT+F4.

  • Pressing the Close button.

Developers can also add custom mechanisms to the client area to close a window, including 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.

To close a window in response to one of these developer-provided mechanisms, you need to call the Close method.

The following example shows how to close a window when the File | Exit menu is clicked:

<Window
    x:Class="CustomMediaPlayerWindow"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Media Player"
    Activated="window_Activated"
    Deactivated="window_Deactivated">
  ...
  <MenuItem Header="_File">
      <MenuItem Header="_Exit" Click="exitMenu_Click" />
  </MenuItem>
  ...
</Window>
using System.Windows;
public partial class CustomMediaPlayerWindow : Window
{
    ...
    void exitMenu_Click(object sender, EventArgs e)
    {
        // Close the window
        this.Close();
    }
}

When a window closes, it raises two events: Closing and Closed.

Closing is raised before the window closes, and allows you to prevent the window from actually closing. One common reason to do this is if window content contains data that needs to be saved, or if some activity is taking place. In these situations, a window can use the Closing event to notify the user and ask them if they'd like to continue closing the window or not. Essentially, this is a backup technique for users who may try to close windows that contain data which hasn't been saved.

You can handle Closing like so:

<Window
    x:Class="CustomMediaPlayerWindow"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Media Player"
    Activated="window_Activated"
    Deactivated="window_Deactivated"
    Closing="window_Closing">
  ...
</Window>
using System.Windows;
public partial class CustomMediaPlayerWindow : Window
{
    ...
    void window_Closing(object sender, CancelEventArgs e)
    {
        // Ask user if they want to close the window
        if (this.isMediaElementPlaying)
        {
            string msg = "Media is playing. Really close?";
            string title = "Custom Media Player?";
            MessageBoxButton buttons = MessageBoxButton.YesNo;
            MessageBoxImage icon = MessageBoxImage.Warning;

            // Show message box and get user's answer
            MessageBoxResult result =
                MessageBox.Show(msg, title, buttons, icon);

            // Don't close window if user clicked No
            e.Cancel = (result == MessageBoxResult.No);
        }
    }
}

The Closing event handler is passed a CancelEventArgs, which exposes a Boolean Cancel property that you set to true to prevent a window from closing.

If Closing is not handled, or it is handled but not canceled, the window will close. Right before a window closes, and after a window can be prevented from closing, Closed is raised.

NoteNote:

An application can be configured to shut down automatically when either the main application window closes (see MainWindow) or the last window closes. See ShutdownMode.

While a window can be explicitly closed through non-client area and client area provided mechanisms, a window can also be implicitly closed as a result of behavior in other parts of the application or Windows, including when:

  • A user either logs off from or shuts down Windows.

  • The owner of a window closes (see Owner).

  • The main application window is closed and ShutdownMode is OnMainWindowClose.

  • Shutdown is called.

NoteNote:

A window cannot be reopened after it is closed.

Window Lifetime Events

The following figure illustrates the key events in the lifetime of a window, and the sequence in which they are raised.

Window events

Window Location

While a window is open, it has an x and y location that is relative to the desktop, which can be ascertained from the Left and Top properties. You can set these properties if you'd like to change the current location of a window. Window also allows you to configure the location that it appears when first opened both on the desktop, and with respect to other windows.

Startup Location

The position that a window appears in when it opens is determined by the WindowStartupLocation property, which can be one of the following WindowStartupLocation enumeration values:

If the startup location is specified as Manual, Window will ask Windows for a position to appear in. You can override this by specifying a location using the Left and Top properties.

Topmost Windows and Z-Order

A window has an x and y position, as specified by its Left and Top properties, respectively. Additionally, a window has a position in the z dimension that determines its vertical position with respect to other windows. This is known as the z-order, of which there are two types: normal z-order and topmost z-order. Windows in the normal z-order are always positioned beneath windows in the topmost z-order. To be positioned in the topmost z-order, a window must set its Topmost property to true:

<Window ... Topmost="True">
  ...
</Window>

Within each z-order, the currently active window appears above all other windows in the same z-order.

The following figure illustrates the effect of the Topmost property on windows in the normal and topmost z-orders.

Illustration of window z-ordering

Window Size

Besides having a desktop position, a window has a size, when it is visible. Window size is actually determined by several Window properties, including the various width and height properties and SizeToContent.

MinWidth, Width, and MaxWidth are used to manage the range of widths that a window can have during its lifetime, and are configured like so:

<Window ... MinWidth="300" Width="400" MaxWidth="500">
  ...
</Window>

The following figure illustrates how these properties are applied to the width range of a window.

Window width illustration

Window height is managed by MinHeight, Height, and MaxHeight, and are configured like so:

<Window ... MinHeight="300" Height="400" MaxHeight="500">
  ...
</Window>

The following figure illustrates how these properties are applied to the height range of a window.

Window height illustration

Because the various width values and various 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. To detect its current width and height by inspecting ActualWidth and ActualHeight, respectively.

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:

  • Manual. No effect (default).

  • Width. Fit to content width; same effect as setting both MinWidth and MaxWidth to the width of the content.

  • Height. Fit to content height; same effect as setting both MinHeight and MaxHeight to the height of the content.

  • WidthAndHeight. Fit to content width and height; same effect as setting both MinHeight and MaxHeight to the height of the content, and setting both MinWidth and MaxWidth to the width of the content.

The following code shows a window that will automatically size to fit its content, both vertically and horizontally, when first shown.

<Window ... SizeToContent="WidthAndHeight">
  ...
</Window>

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. To ensure a valid range is maintained, Window evaluates the values of the size properties using the following orders of precedence.

  • For height properties:

    System.Windows.FrameworkElement.MinHeight > System.Windows.FrameworkElement.MaxHeight > System.Windows.SizeToContent.Height/System.Windows.SizeToContent.WidthAndHeight > System.Windows.FrameworkElement.MaxHeight

  • For width properties:

    System.Windows.FrameworkElement.MinWidth > System.Windows.FrameworkElement.MaxWidth >

    System.Windows.SizeToContent.Width/System.Windows.SizeToContent.WidthAndHeight > System.Windows.FrameworkElement.MaxWidth

You can use the Window Sizing Order of Precedence Sample to experiment with the order of precedence.

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 using either a resize grip, if visible, or the border, if resizable.

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 will relocate 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. The following figure shows both types of minimized windows:

A window with a maximized state expands to the maximize 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 using either a resize grip or by dragging the border.

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 will be shown as maximized when it opens.

<Window ... WindowState="Maximized">
  ...
</Window>

In general, you'll likely set WindowState to configure the initial state of a window. Once a window that can be resized is shown, users will use the minimize, maximize, and restore buttons on the window's title bar to change its 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. To configure the non-client area, Window provides several properties that 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's task bar.

Resize Mode

Depending on the WindowStyle, you can change how the user will resize the window, or whether they can at all. While being related to sizing, 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.

You can configure how a window resizes by setting its ResizeMode property, which can be one of the following ResizeMode enumeration values:

The following figure illustrates the effect of each.

Window resize modes

As with WindowStyle, the resize mode of a window is unlikely to change during it's lifetime, which means that you'll most likely set it from markup:

<Window ... ResizeMode="CanResizeWithGrip">
    ...
</Window>

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.

To control what type of border a window gets, you set its WindowStyle property with one of the values of the WindowStyle enumeration, which are:

The effect of these window styles are illustrated in the following figure.

Window styles

You can set WindowStyle using either markup or code, although, because it is unlikely to change during the lifetime of a window, you will most likely configure it using markup:

<Window ... WindowStyle="ToolWindow">
    ...
</Window>

Non-Rectangular Window Style

There are also situations where the border styles that WindowStyle allows you to have are not sufficient. For example, you may want to create an application with a non-rectangular border, like Microsoft Windows Media Player uses.

For example, consider the speech bubble window shown in the following figure.

Nonrectangular window

This type of window can be created by setting the WindowStyle attribute to None (None), and by using special support that Window has for transparency:

<Window ...
  WindowStyle="None"
  AllowsTransparency="True"
  Background="Transparent">
    ...
</Window>

This combination of WindowStyle, AllowsTransparency, and Background attributes and values instructs the window to render completely transparent. This allows you to then provide your own border, by using a Path for example:

<Window ...
  WindowStyle="None" 
  AllowsTransparency="True" 
  Background="Transparent">
    ...
    <!-- Path and fill for speech bubble UI -->
    <Path Stroke="DarkGray" StrokeThickness="2">
        ...
    </Path>
    ...
</Window>

If you do create a non-rectangular border for your window, that means you cannot use the WPF-provided non-client area elements and, consequently, must implement your own.

See Non-Rectangular Windows Sample.

Task Bar Presence

The default appearance of a window includes a task bar 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). You can toggle whether the task bar button for a window is shown by setting the ShowInTaskbar property (true by default):

<Window ... ShowInTaskbar="False">
    ...
</Window>

Security Considerations

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.

However, this falls outside the set of permissions granted to applications that are launched from the Internet or LocalIntranet using ClickOnce. Consequently, users will receive a ClickOnce security warning, and will need to elevate the permission set for the application to full trust.

Additionally, XBAPs cannot show windows or dialog boxes by default. See Windows Presentation Foundation Security Strategy - Platform Security for a discussion on standalone application security considerations.

See Also

Reference

Window
MessageBox
NavigationWindow
Application

Concepts

Dialog Boxes Overview
Building a Windows Presentation Foundation Application