Общие сведения об окнах WPF (WPF .NET)

Пользователи взаимодействуют с приложениями Windows Presentation Foundation (WPF) с помощью окон. Основная цель окна — разместить содержимое, которое визуализирует данные и позволяет пользователям взаимодействовать с ними. Приложения WPF предоставляют собственные окна с помощью класса Window. Эта статья содержит ознакомительные сведения о Window, которые необходимо изучить прежде, чем приступать к созданию окон в приложениях и управлению ими.

Важно!

В этой статье используется XAML, созданный на основе проекта C#. Если вы используете Visual Basic, XAML может выглядеть немного иначе. Эти различия, как правило, присутствуют в значениях атрибутов x:Class. C# в отличие от Visual Basic включает корневое пространство имен для проекта.

Шаблоны проектов для C# создают тип App, содержащийся в файле app.xaml. В Visual Basic тип имеет имя Application, а файл — Application.xaml.

Класс окна

В WPF окно инкапсулируется классом Window, который позволяет выполнять следующие задачи.

  • Отобразить окно.
  • Настроить размер, положение и внешний вид окна.
  • Разместить содержимое конкретного приложения.
  • Управлять временем существования окна.

На следующем рисунке показаны составные части окна.

Screenshot that shows parts of a WPF window.

Окно разделено на две области: неклиентскую и клиентскую.

Неклиентская область окна реализуется WPF и включает части окна, которые являются общими для большинства окон, в том числе следующие:

  • Заголовок окна (1–5).
  • Значок (1).
  • Заголовок (2).
  • Кнопки «Свернуть» (3), «Развернуть» (4) и «Закрыть» (5).
  • Системное меню (6) с пунктами меню. Появляется по нажатию значка (1).
  • Граница (7).

Клиентская область окна находится внутри неклиентской области и используется разработчиками для добавления содержимого конкретного приложения, такого как строки меню, панели инструментов и элементы управления.

  • Клиентская область (8).
  • Изменение размера захвата (9). Это элемент управления, добавленный в клиентскую область (8).

Реализация окна

Реализация типичного окна включает внешний вид и поведение. Внешний вид определяет, как окно отображается для пользователей, а поведение — функционирование окна при взаимодействии пользователей с ним. В WPF внешний вид и поведение окна можно реализовать с помощью кода или разметки XAML.

Однако обычно внешний вид окна реализуется с помощью разметки XAML, а его поведение — с помощью кода программной части, как показано в следующем примере.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->
    
</Window>

Ниже представлен код программной части для XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}
Public Class Window1

End Class

Чтобы разрешить совместную работу файла разметки XAML и файла кода программной части, необходимо следующее:

  • В разметке элемент Window должен включать атрибут x:Class. При построении приложения существование атрибута x:Class заставляет Microsoft Build Engine (MSBuild) создавать класс partial, который является производным от Window и имеет имя, указанное в атрибуте x:Class. Для этого требуется добавить объявление пространства имен XAML в схему XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"). Созданный класс partial реализует метод InitializeComponent, который вызывается для регистрации событий и установки свойств, реализованных в разметке.

  • В коде программной части класс должен быть классом partial с тем же именем, которое определено атрибутом x:Class в разметке. Кроме того, он должен быть производным от Window. Это позволяет связать файл кода программной части с классом partial, созданным для файла разметки при построении приложения. Дополнительные сведения см. в разделе Компиляция приложения WPF.

  • В коде программной части класс Window должен реализовывать конструктор, который вызывает метод InitializeComponent. Метод InitializeComponent реализуется классом partial, созданным файлом разметки, для регистрации событий и задания свойств, определенных в разметке.

Примечание.

При создании нового класса Window для проекта с помощью Visual Studio классWindow реализуется с использованием разметки и кода программной части, а также включает в себя необходимую конфигурацию для создания связи между файлами разметки и кода программной части, как описано здесь.

При такой конфигурации можно сосредоточиться на определении внешнего вида окна в разметке XAML и реализации его поведения в коде программной части. Ниже представлен пример окна с кнопкой, которая определяет обработчик событий для события Click. Это реализуется в XAML, а обработчик — в коде программной части.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->

    <Button Click="Button_Click">Click This Button</Button>
    
</Window>

Ниже представлен код программной части для XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button was clicked.");
        }
    }
}
Public Class Window1

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        MessageBox.Show("Button was clicked.")
    End Sub

End Class

Настройка окна для MSBuild

Реализация окна определяет его конфигурацию для MSBuild. Для окна, которое определяется с помощью разметки XAML и кода программной части:

  • Файлы разметки XAML настраиваются как элементы Page MSBuild.
  • Файлы кода программной части настраиваются как элементы CompileMSBuild.

Проекты пакета SDK для .NET автоматически импортируют правильные элементы Page и Compile, поэтому объявлять эти элементы не нужно. Если проект настроен для WPF, файлы разметки XAML автоматически импортируются как элементы Page, а соответствующий файл кода программной части — как Compile.

Проекты MSBuild не будут автоматически импортировать типы, поэтому объявлять их следует самостоятельно:

<Project>
    ...
    <Page Include="MarkupAndCodeBehindWindow.xaml" />
    <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />
    ...
</Project>

Сведения о построении приложений см. в разделе Компиляция приложения WPF.

Время существования окна

Как и любой класс, окно имеет время существования, которое начинается с момента создания его экземпляра, после чего оно открывается, активируется/деактивируется и в конечном счете закрывается.

Открытие окна

Чтобы открыть окно, сначала создайте его экземпляр, как показано в следующем примере.

using System.Windows;

namespace WindowsOverview
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // Create the window
            Window1 window = new Window1();

            // Open the window
            window.Show();
        }
    }
}
Class Application

    Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
        ' Create the window
        Dim window As New Window1

        ' Open the window
        window.Show()
    End Sub

End Class

В этом примере экземпляр Window1 создается при запуске приложения, когда возникает событие Startup. Дополнительные сведения об окне запуска см. в разделе Получение или задание главного окна приложения.

При создании экземпляра окна ссылка на него автоматически добавляется в список окон, находящийся под управлением объекта Application. Первое окно, экземпляр которого создается, Application автоматически устанавливает в качестве главного окна приложения.

Наконец, окно открывается путем вызова метода Show, как показано на следующем изображении:

WPF Window with a single button inside.

Окно, которое открывается путем вызоваShow, является безрежимным, и приложение не запрещает пользователям взаимодействовать с другими окнами в приложении. Метод ShowDialog открывает окно как модальное и запрещает взаимодействие пользователя с конкретным окном. Дополнительные сведения см. в разделе Общие сведения о диалоговых окнах.

При вызове Show перед своим отображением окно выполняет работу по инициализации, чтобы установить инфраструктуру, которая позволяет ему получать данные, вводимые пользователем. После инициализации окна возникает событие SourceInitialized и окно отображается.

Дополнительные сведения см. в разделе Открытие окна или диалогового окна.

Окно запуска

В предыдущем примере событие Startup использовалось для выполнения кода, отображающего начальное окно приложения. Вместо этого используйте команду StartupUri, чтобы указать путь к XAML-файлу в приложении. Приложение автоматически создает и отображает окно, указанное этим свойством.

<Application x:Class="WindowsOverview.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WindowsOverview"
             StartupUri="ClippedWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Владение окном

Окно, открытое путем вызова метода Show, не имеет неявной связи с окном, создавшим его. Пользователи могут взаимодействовать с любым окном независимо от другого. Это означает, что любое из окон может выполнять следующие действия.

  • Перекрывать другое (за исключением случая, когда свойству Topmost одного из окон задано значение true).
  • Сворачиваться, разворачиваться и восстанавливаться без влияния на другое окно.

Для некоторых окон требуется связь с окном, которое их открывает. Например приложение IDE может открывать окна свойств и окна инструментов, типичное поведение которых заключается в том, чтобы перекрыть окно, которое их создает. Кроме того, такие окна должны всегда закрываться, сворачиваться, разворачиваться и восстанавливаться вместе с окном, которое их создало. Такую связь можно установить, сделав одно окно владельцем другого. Для этого устанавливается свойство Ownerокна во владении со ссылкой на окно-владелец. Это показано в следующем примере.

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Create a window and make the current window its owner
    var ownedWindow = new ChildWindow1();
    ownedWindow.Owner = this;
    ownedWindow.Show();
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Create a window and make the current window its owner
    Dim ownedWindow As New ChildWindow1
    ownedWindow.Owner = Me
    ownedWindow.Show()
End Sub

После установки владения:

  • Окно во владении может ссылаться на окно-владелец, проверяя значение его свойства Owner.
  • Окно-владелец может найти все принадлежащие ему окна, проверив значение его свойства OwnedWindows.

Активация окна

При первом открытии окно становится активным. Активным окном является окно, которое в настоящий момент захватывает входные данные пользователя, например нажатие клавиш и щелчки мышью. Становясь активным, окно вызывает событие Activated.

Примечание.

При первом открытии окна события Loaded и ContentRendered запускаются только после запуска события Activated. С учетом этого окно может считаться открытым, если запущено событие ContentRendered.

После активизации окна пользователь может активировать другое окно в том же приложении или активировать другое приложение. В таком случае текущее активное окно становится неактивным и вызывает событие Deactivated. Аналогичным образом, когда пользователь выбирает неактивное окно, оно снова становится активным и запускается событие Activated.

Одна из распространенных причин обработки Activated и Deactivated — включение и отключение функций, которые могут выполняться, только если окно активно. Например, некоторые окна отображают интерактивное содержимое, которое требует постоянного ввода данных или внимания пользователя, включая игры и видеопроигрыватели. Ниже в качестве примера приведен упрощенный видеопроигрыватель, демонстрирующий обработку Activated и Deactivated для реализации этого повеления.

<Window x:Class="WindowsOverview.CustomMediaPlayerWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Activated="Window_Activated"
        Deactivated="Window_Deactivated"
        Title="CustomMediaPlayerWindow" Height="450" Width="800">
    <Grid>
        <MediaElement x:Name="mediaElement" Stretch="Fill"
                      LoadedBehavior="Manual" Source="numbers.mp4" />
    </Grid>
</Window>

Ниже представлен код программной части для XAML.

using System;
using System.Windows;

namespace WindowsOverview
{
    public partial class CustomMediaPlayerWindow : Window
    {
        public CustomMediaPlayerWindow() =>
            InitializeComponent();

        private void Window_Activated(object sender, EventArgs e)
        {
            // Continue playing media if window is activated
            mediaElement.Play();
        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            // Pause playing if media is being played and window is deactivated
            mediaElement.Pause();
        }
    }
}
Public Class CustomMediaPlayerWindow
    Private Sub Window_Activated(sender As Object, e As EventArgs)
        ' Continue playing media if window Is activated
        mediaElement.Play()
    End Sub

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

Другие типы приложений могут выполнять код в фоновом режиме, когда окно деактивировано. Например, почтовый клиент может продолжать опрашивать почтовый сервер, пока пользователь работает с другими приложениями. Такие приложения часто обеспечивают другое или дополнительное поведение, когда главное окно не активно. В случае почтовой программы это может означать как добавление нового почтового элемента в папку "Входящие", так и добавление значка уведомления на панель задач. Значок уведомления должен отображаться только в том случае, если окно почты не активно. Это определяется путем проверки свойства IsActive.

Если фоновая задача завершается, окно может уведомить пользователя в более срочном порядке, вызвав метод Activate. Если пользователь взаимодействует с другим приложением, которое активно при вызове Activate, то кнопка панели задач окна мигает. Однако если пользователь взаимодействует с текущим приложением, вызов Activate перенесет окно на передний план.

Примечание.

Активировать область видимости приложения можно с помощью событий Application.Activated и Application.Deactivated.

Предотвращение активации окна

Существуют сценарии, в которых окна не должны активироваться при отображении, например окна сеанса обмена сообщениями в приложениях чатов или окна уведомлений приложения электронной почты.

Если приложение содержит окно, которое не должно активироваться при отображении, можно задать для его свойства ShowActivated значение false перед первым вызовом метода Show. Результат:

  • Окно не активируется.
  • Событие окна Activated не запускается.
  • Текущее активированное окно останется активным.

Однако окно активируется, если пользователь щелкнет его неклиентскую или клиентскую область. В данном случае:

  • Окно активируется.
  • Событие окна Activated запускается.
  • Ранее активированное окно деактивируется.
  • Затем события окна Deactivated и Activated запускаются в ответ на действия пользователя.

Закрытие окна

Время существования окна заканчивается, когда пользователь его закрывает. После закрытия окна открыть его повторно нельзя. Окно может быть закрыто с помощью элементов в неклиентской области, включая следующие:

  • Элемент Закрыть меню Система.
  • Нажатие клавиш ALT+F4.
  • Нажатие кнопки Закрыть.
  • Нажатие клавиши ESC, если свойство кнопки IsCancel имеет значение true в модальном окне.

Можно указать дополнительные способы закрытия окна для клиентской области, к наиболее типичным из которых относятся следующие:

  • Элемент Выход в меню Файл, обычно для главных окон приложений.
  • Элемент Закрыть в меню Файл, как правило, применим для вторичных окон приложений.
  • Кнопка Отменить, обычно для модального диалогового окна.
  • Кнопка Закрыть, обычно для немодального диалогового окна.

Чтобы закрыть окно одним из данных пользовательских способов, необходимо вызвать метод Close. В следующем примере реализуется возможность закрытия окна выбором пункта Выход в меню Файл.

<Window x:Class="WindowsOverview.ClosingWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClosingWindow" Height="450" Width="800">
    <StackPanel>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
            </MenuItem>
        </Menu>
    </StackPanel>
</Window>

Ниже представлен код программной части для XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class ClosingWindow : Window
    {
        public ClosingWindow() =>
            InitializeComponent();

        private void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Close the current window
            this.Close();
        }
    }
}
Public Class ClosingWindow
    Private Sub fileExitMenuItem_Click(sender As Object, e As RoutedEventArgs)
        ' Close the current window
        Me.Close()
    End Sub
End Class

Примечание.

Приложение можно настроить на автоматическое завершение работы при закрытии главного окна приложения (см. MainWindow) или при закрытии последнего окна. Дополнительные сведения см. в разделе ShutdownMode.

Хотя окно может быть непосредственно закрыто с помощью механизмов, предоставляемых в неклиентской и клиентской областях, оно также может быть неявно закрыто в результате поведения в других частях приложения или Windows, включая следующее:

  • Пользователь выходит из системы или завершает работу Windows.
  • Owner окна закрывается.
  • Главное окно приложения закрыто, а ShutdownMode — OnMainWindowClose.
  • Вызывается метод Shutdown.

Важно!

После закрытия окно нельзя открыть повторно.

Отмена закрытия окна

При закрытии окно запускает два события: Closing и Closed.

Closing вызывается перед закрытием окна и предоставляет механизм, с помощью которого можно предотвратить закрытие окна. Одна из распространенных причин, препятствующих закрытию окна, заключается в том, что содержимое окна содержит измененные данные. В этом случае событие Closing может быть обработано, чтобы определить наличие необработанных данных и запросить у пользователя, следует ли закрыть окно без сохранения данных или отменить закрытие окна. В следующем примере показаны ключевые аспекты обработки Closing.

<Window x:Class="WindowsOverview.DataWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataWindow" Height="450" Width="800"
        Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="documentTextBox" TextChanged="documentTextBox_TextChanged" />
    </Grid>
</Window>

Ниже представлен код программной части для XAML.

using System.Windows;
using System.Windows.Controls;

namespace WindowsOverview
{
    public partial class DataWindow : Window
    {
        private bool _isDataDirty;

        public DataWindow() =>
            InitializeComponent();

        private void documentTextBox_TextChanged(object sender, TextChangedEventArgs e) =>
            _isDataDirty = true;

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // If data is dirty, prompt user and ask for a response
            if (_isDataDirty)
            {
                var result = MessageBox.Show("Document has changed. Close without saving?",
                                             "Question",
                                             MessageBoxButton.YesNo);

                // User doesn't want to close, cancel closure
                if (result == MessageBoxResult.No)
                    e.Cancel = true;
            }
        }
    }
}
Public Class DataWindow

    Private _isDataDirty As Boolean

    Private Sub documentTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)
        _isDataDirty = True
    End Sub

    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)

        ' If data is dirty, prompt user and ask for a response
        If _isDataDirty Then
            Dim result = MessageBox.Show("Document has changed. Close without saving?",
                                         "Question",
                                         MessageBoxButton.YesNo)

            ' User doesn't want to close, cancel closure
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End If

    End Sub
End Class

В обработчик событий Closing передается событие CancelEventArgs, реализующее свойство Cancel, для которого задается значение true с целью предотвратить закрытие окна.

Если событие Closing не обработано или обработано, но не закрыто, окно закроется. Непосредственно перед фактическим закрытием окна запускается Closed. На этом этапе невозможно предотвратить закрытие окна.

События времени существования окна

На следующем рисунке показана последовательность основных событий на протяжении времени существования окна.

Diagram that shows events in a window's lifetime.

На рисунке показана последовательность основных событий на протяжении времени существования окна, которое отображается без активации (ShowActivated установлен равным false до отображения окна).

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

Расположение окна

Когда окно открыто, оно располагается в координатах x и y относительно рабочего стола. Чтобы определить расположение, необходимо проверить свойства Left и Top соответственно. Задайте эти свойства, чтобы изменить расположение окна.

Можно также указать начальное расположение окна Window при первом появлении путем задания свойству WindowStartupLocation одного из следующих значений перечисления WindowStartupLocation:

Если расположение запуска указано как Manual, а свойства Left и Top не заданы, Window запросит у операционной системы расположение для отображения.

Окна верхнего уровня и Z-порядок

Помимо расположения в координатах x и y, окно имеет координату по оси z, которая определяет его вертикальную позицию относительно других окон. Это называется z-порядком окна. Существует два типа: обычный z-порядок и верхний z-порядок. Расположение окна в обычном z-порядке определяется тем, активно оно в данный момент или нет. По умолчанию окно находится в обычном z-порядке. Расположение окна в верхнем z-порядке также определяется тем, активно оно в данный момент или нет. Кроме того, окна в самом верхнем z-порядке всегда расположены над окнами в обычном z-порядке. Окно располагается в самом верхнем z-порядке путем установки для его свойства Topmost значения true.

В каждом z-порядке активное в данный момент окно появляется поверх всех других окон в том же z-порядке.

Размер окна

Помимо расположения на рабочем столе, окно имеет размер, определяемый несколькими свойствами, включая различные свойства ширины и высоты и SizeToContent.

MinWidth, Width и MaxWidth используются для управления диапазоном значений ширины, которые может иметь окно на протяжении своего времени существования.

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

Высота окна управляется MinHeight, Height и MaxHeight.

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

Так как различные значения ширины и высоты определяют диапазон, ширина и высота изменяемого окна могут находиться в любом месте указанного диапазона для соответствующего измерения. Чтобы определить текущую ширину и высоту, проверьте свойства ActualWidth и ActualHeight соответственно.

Если ширина и высота окна должны соответствовать размеру содержимого, можно использовать свойство SizeToContent, которое имеет следующие значения:

  • SizeToContent.Manual.
    Нет эффекта (по умолчанию).
  • SizeToContent.Width.
    Соответствие ширине содержимого. Дает такой же эффект, как задание свойствам MinWidth и MaxWidth значения ширины содержимого.
  • SizeToContent.Height.
    Соответствие высоте содержимого. Дает такой же эффект, как задание свойствам MinHeight и MaxHeight значения высоты содержимого.
  • SizeToContent.WidthAndHeight.
    Соответствие ширине и высоте содержимого. Дает такой же эффект, как задание свойствам MinHeight и MaxHeight значения высоты содержимого, а свойствам MinWidth и MaxWidth — ширины.

В следующем примере показано окно, размеры которого автоматически устанавливаются равными его содержимому по вертикали и по горизонтали при первом отображении.

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

В следующем примере показано, как задать в коде свойство SizeToContent, чтобы указать изменение размеров окна в соответствии с его содержимым.

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

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

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

// Automatically resize height and width relative to content
this.SizeToContent = SizeToContent.WidthAndHeight;
' Manually alter window height and width
Me.SizeToContent = SizeToContent.Manual

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

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

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

Порядок приоритета для свойств размера

Различные свойства размеров окна объединяются для определения диапазона ширины и высоты окна изменяемого размера. Чтобы не выходить за рамки допустимого диапазона, Window оценивает значения свойств размера с использованием следующего порядка приоритета.

Для свойств высоты:

  1. FrameworkElement.MinHeight
  2. FrameworkElement.MaxHeight
  3. SizeToContent.Height / SizeToContent.WidthAndHeight
  4. FrameworkElement.Height

Для свойств ширины:

  1. FrameworkElement.MinWidth
  2. FrameworkElement.MaxWidth
  3. SizeToContent.Width / SizeToContent.WidthAndHeight
  4. FrameworkElement.Width

Порядок приоритетов также может определять размер окна, когда оно развернуто, что определяется с помощью свойства WindowState.

Window state

В течение времени существования окна изменяемого размера оно может иметь три состояния: обычное, свернутое и развернутое. Окно с обычным состоянием является состоянием окна по умолчанию. Окно с этим состоянием позволяет пользователю перемещать его и изменять размер, используя захват для изменения размера или границу.

Окно со свернутым состоянием сворачивается в кнопку на панели задач, если для параметра ShowInTaskbar установлено значение true. В противном случае оно сворачивается до минимально возможного размера и перемещается в нижний левый угол рабочего стола. Ни один из типов свернутого окна не может быть изменен с помощью границы или захвата для изменения размера, хотя свернутое окно, которое не отображается на панели задач, можно перетаскивать на рабочем столе.

Окно с развернутым состоянием разворачивается до максимально возможного размера, который не может превышать значения свойств MaxWidth, MaxHeight и SizeToContent. Как и для свернутого окна, размер развернутого окна нельзя изменить с помощью захвата для изменения размера или перетаскивания границы.

Примечание.

Значения свойств окна Top, Left, Width и Height всегда представляют значения для обычного состояния, даже если окно в текущий момент развернуто или свернуто.

Состояние окна можно настроить путем задания его свойства WindowState, которое может иметь одно из следующих значений перечисления WindowState:

В следующем примере показано создание окна, которое отображается развернутым при его открытии.

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

В общем случае следует задать WindowState для настройки начального состояния окна. После отображения окна изменяемого размера пользователи могут нажимать кнопки свертывания, развертывания и восстановления на панели заголовка окна, чтобы изменить состояние окна.

Внешний вид окна

Можно изменить внешний вид клиентской области окна, добавляя в нее определенное содержимое, такое как кнопки, метки и текстовые поля. Для настройки неклиентской области Window предоставляет несколько свойств, в том числе Icon для задания значка окна и Title для задания его заголовка.

Можно также изменить внешний вид и поведение границы неклиентской области, настраивая режим изменения размера окна, стиль окна и отображение в виде кнопки на панели задач рабочего стола.

Режим изменения размера

Свойство WindowStyle позволяет разрешать или запрещать пользователям изменять размер окна, а также контролировать данный процесс. Стиль окна влияет на следующее:

  • разрешение или запрет изменения размера путем перетаскивания границы окна с помощью мыши;
  • отображение кнопок Свернуть, Развернуть и Закрыть в неклиентской области;
  • включение кнопок Свернуть, Развернуть и Закрыть.

Изменение размера окна можно настроить путем задания его свойства ResizeMode, которое может иметь одно из следующих значений перечисления ResizeMode:

Как и в случае WindowStyle, режим изменения размера окна редко изменяется на протяжении времени существования. Это означает, что, скорее всего, он устанавливается из разметки XAML.

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

Обратите внимание, что определить, развернуто, свернуто или восстановлено окно, можно путем проверки свойства WindowState.

Window style

Граница, предоставляемая из неклиентской области окна, подходит для большинства приложений. Однако существуют ситуации, когда требуются различные типы границ либо границы вовсе не требуются, в зависимости от типа окна.

Для управления типом границы окна его свойству WindowStyle задается одно из следующих значений перечисления WindowStyle:

Эффект применения стиля окна показан на следующем рисунке:

Screenshot that shows how WindowStyle affects a window in WPF.

Обратите внимание, что на изображении выше отсутствуют заметные различия между SingleBorderWindow и ThreeDBorderWindow. В Windows XP стиль ThreeDBorderWindow влиял на внешний вид окна, добавляя трехмерную границу в клиентскую область. Начиная с Windows 7 различия между двумя стилями минимальны.

Задать WindowStyle можно с помощью разметки XAML или кода. Поскольку он вряд ли изменится на протяжении времени существования окна, вы, скорее всего, настроите его с помощью разметки XAML.

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

Непрямоугольный стиль окна

В некоторых ситуациях стилей границы, которые предлагает WindowStyle, недостаточно. Например, можно создать приложение с непрямоугольной границей, такой, как используется проигрывателем мультимедиа Microsoft Windows.

Рассмотрим окно "облачко с текстом", показанное на следующем изображении.

Screenshot of a WPF window that has a clipped area and custom shape.

Окно такого типа можно создать путем задания свойству WindowStyle значения None, а также использования поддержки прозрачности, предоставляемой Window.

<Window x:Class="WindowsOverview.ClippedWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClippedWindow" SizeToContent="WidthAndHeight"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>

        <Rectangle Stroke="#FF000000" RadiusX="10" RadiusY="10"/>
        <Path Fill="White" Stretch="Fill" Stroke="#FF000000" HorizontalAlignment="Left" Margin="15,-5.597,0,-0.003" Width="30" Grid.Row="1" Data="M22.166642,154.45381 L29.999666,187.66699 40.791059,154.54395"/>
        <Rectangle Fill="White" RadiusX="10" RadiusY="10" Margin="1"/>
        
        <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="25" Text="Greetings!" TextWrapping="Wrap" Margin="5,5,50,5"/>
        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="{x:Null}" Foreground="Red" Content="❌" FontSize="15" />

        <Grid.Effect>
            <DropShadowEffect BlurRadius="10" ShadowDepth="3" Color="LightBlue"/>
        </Grid.Effect>
    </Grid>
</Window>

Это сочетание значений указывает, что окно отрисовывается прозрачным. В этом состоянии кнопки оформления неклиентской области окна нельзя использовать, поэтому необходимо предоставить собственные.

Наличие панели задач

Внешний вид окна по умолчанию включает кнопку панели задач. У некоторых типов окон нет кнопки панели задач. К таким окнам относятся, например, окна сообщений, диалоговые окна или окна, у которых для свойства WindowStyle задано значение ToolWindow. Можно управлять отображением кнопки панели задач для окна, задав свойство ShowInTaskbar (true по умолчанию).

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

Другие типы окон

NavigationWindow — это окно, предназначенное для размещения перемещаемого содержимого.

Диалоговые окна — это окна, которые часто используются для сбора информации от пользователя для выполнения функции. Например, когда пользователь хочет открыть файл, приложение отображает диалоговое окно Открыть файл, чтобы получить имя файла от пользователя. Дополнительные сведения см. в разделе Общие сведения о диалоговых окнах.

См. также