Класс Window

Класс Window унаследован от класса ContentControl. Это означает, что он может содержать только одного потомка (каковым обычно является контейнер компоновки наподобие элемента управления Grid) и что его фон можно закрашивать с помощью кисти путем установки свойства Background.
Можно еще также использовать и свойства BorderBrush и BorderThickness для добавления вокруг окна границы, но эта граница добавляется внутри оконной рамки (то есть по краю клиентской области). Оконную рамку можно вообще удалять путем установки для свойства WindowStyle значения None, что позволяет создавать полностью настраиваемое (т.е. имеющее специальную форму) окно.
— это область внутри окна. Именно в ней размещается содержимое. К не клиентской области относится граница и строка заголовка в верхней части окна. За управление этой областью отвечает операционная система.
Помимо этого, класс Window имеет небольшой набор членов, знакомых любому программисту для Windows. Наиболее очевидными из них являются свойства, которые касаются внешнего вида и позволяют изменять способ отображения не клиентской части окна. Основные члены класса Window перечислены ниже:
AllowsTransparency
Если установлено в true, класс Window позволяет другим окнам «проглядывать» через данное при условии, что для фона был установлен прозрачный цвет. В случае установки в false (поведение по умолчанию), находящееся позади данного окна содержимое не «просматривается», и прозрачный цвет фона визуализируется как черный. В случае использования в комбинации со свойством WindowsStyle, установленным в None, это свойство позволяет создавать окна, имеющие необычную форму.
Icon
Объект imageSource, идентифицирующий значок, который должен использоваться для данного окна. Значки отображаются в левом верхнем углу окна (если в нем применяется один из стандартных стилей границ), в панели задач (если свойство ShowInTaskBar установлено в true) и в окне выбора, которое появляется, когда пользователь нажимает комбинацию клавиш для перехода между работающими приложениями. Поскольку эти значки имеют разные размеры, в используемом для них файле .ico должны содержаться изображения с размерами как минимум 16×16 и 32×32 пикселя.
В последних версиях ОС Windows (Windows Vista и Windows 7) добавлен новый стандарт для значков 48×48 и 256×256 пикселей, размер которых можно изменять. Если свойство Icon установлено в null, окно получает тот же значок, что и приложение (значок для которого можно указать в Visual Studio, дважды щелкнув на узле Properties (Свойства) в окне Solution Explorer и перейдя на вкладку Application (Приложение)). Если свойство вообще опущено, WPF для изображения окна будет использовать стандартный, но непримечательный значок
Тор и Left
Определяют расстояние между левым верхним углом окна и левыми верхними краями экрана (в независимых от устройства единицах). При изменении любого из них генерируется событие LocationChanged. Если свойство WindowStartupPosition установлено в Manual, значения этих свойств можно указывать до появления окна для определения, задавая его начальную позицию. Какое бы значение не использовалось для WindowStartupPosition, эти свойства можно устанавливать в любой момент после отображения окна, изменяя его текущую позицию
ResizeMode
Принимает значение перечисления ResizeMode, которое определяет, может ли пользователь изменять размеры окна. Также влияет на видимость кнопок, отвечающих за разворачивание и сворачивание окна. Чтобы полностью заблокировать размеры окна, используйте значение NoResize. Чтобы пользователь мог только сворачивать окно, применяйте значение CanMinimize. Чтобы пользователь мог изменять размер окна всеми возможными способами, указываете значение CanResize. Чтобы в правом нижнем углу окна отображалась еще и визуальная подсказка, указывающая, что размеры окна разрешено изменять, задавайте значение CanResizeWithGrip.
RestoreBounds
Предоставляет границы окна. Если окно в текущий момент развернуто или свернуто, это свойство отражает границы, которые использовались последними перед развертыванием или свертыванием. Это чрезвычайно удобно, когда необходимо сохранить информацию о позиции и размерах окна.
ShowInTaskBar
Если установлено в true, окно отображается в панели задач и списке, появляющемся после нажатия комбинации клавиш . Обычно это свойство устанавливается в true только для главного окна приложения.
SizeToContent
Позволяет создать окно, которое автоматически увеличивается в соответствии с размерами содержимого. Это свойство принимает значение перечисления SizeToContent. Чтобы отключить автоматическое изменение размеров окна, используйте значение Manual. Чтобы окно могло увеличиваться в различных направлениях в соответствии с размерами динамического содержимого, применяйте, соответственно, значение Height, Width или WidthAndHeight. При установке значения SizeToContent окно может увеличиваться в размерах в соответствии с содержимым так, что будет выходить за пределы экрана.
Title
Заголовок, который отображается в строке заголовка окна (и в панели задач)
Topmost
Если установлено в true, окно всегда отображается поверх остальных окон в приложении (если только у них это свойство также не равно true). Такая настройка очень удобна для палитр, которые обычно должны «плавать» над другими окнами
WindowStartupLocation
Принимает значение перечисления WindowStartupLocation. Для размещения окна в конкретной позиции с помощью свойств Left и Тор используйте значение Manual. Для размещения окна по центру экрана применяйте значение CenterScreen. Для размещения окна с учетом позиции того окна, которое его запустило, указывайте значение CenterOwner. При отображении немодального окна с использованием значения CenterOwner удостоверьтесь, что свойство Owner нового окна установлено перед тем, как показывать его.
WindowState
Принимает значение перечисления WindowState. Информирует о том, в каком состоянии находится окно: развернутом, свернутом или обычном (и позволяет изменить его). При изменении значения этого свойства генерируется событие StateChanged
WindowStyle
Принимает значение перечисления WindowStyle, которое определяет внешний вид границы окна. Возможные значения: SingleBorderWindow (по умолчанию), ThreeDBorderWindow (граница визуализируется несколько иным образом в Windows ХР), ToolWindow (отображается тонкая граница, удобная для «плавающих» окон с инструментами без кнопок сворачивания и разворачивания) и None (визуализируется очень тонкая приподнятая граница без области для строки заголовка). Увидеть разницу можно на рисунке ниже:
Минимальные и максимальные размеры

Каждый элемент включает свойства Height и Width, которые позволяют установить явные размеры. Однако предпринимать такой шаг — не слишком хорошая идея. Вместо этого при необходимости используйте свойства минимальных и максимальных размеров, чтобы зафиксировать элемент управления в нужных пределах размеров.
Подумайте дважды, прежде чем устанавливать явные размеры в WPF. В хорошо спроектированной компоновке подобная необходимость возникать не должна. Если вы добавляете информацию о размерах, то рискуете создать хрупкую компоновку, которая не сможет адаптироваться к изменениям (вроде разных языков и размеров окна) и будет усекать содержимое.
Например, можно решить, что кнопки в панели StackPanel должны растягиваться для ее заполнения, но иметь ширину не более 200 и не менее 100 единиц. (По умолчанию кнопки начинаются с минимальной ширины в 75 единиц.) Ниже показана разметка, которая для этого понадобится:
Когда панель StackPanel изменяет размеры кнопки, она принимает во внимание несколько единиц информации:
Минимальный размер
Каждая кнопка всегда будет не меньше минимального размера.
Максимальный размер
Каждая кнопка всегда будет меньше максимального размера (если только вы не установите неправильно максимальный размер меньше минимального).
Содержимое
Если содержимое внутри кнопки требует большей ширины, то StackPanel попытается увеличить кнопку. (Для определения размера, необходимого кнопке, можно проверить свойство DesiredSize, которое вернет минимальную ширину или ширину содержимого — в зависимости от того, что из них больше.)
Размер контейнера
Если минимальная ширина больше, чем ширина StackPanel, то часть кнопки будет усечена. В противном случае кнопке не позволено будет расти шире, чем позволит StackPanel, несмотря на то, что она не сможет вместить весь текст на своей поверхности.
Горизонтальное выравнивание
Поскольку кнопка использует значение HorizontalAlignment, равное Stretch (по умолчанию), панель StackPanel попытается увеличить кнопку, чтобы она заполнила всю ширину панели.
Сложность понимания этого процесса заключается в том, что минимальный и максимальный размеры устанавливают абсолютные пределы. Без этих пределов панель StackPanel пытается обеспечить желаемый размер кнопки (чтобы вместить ее содержимое) и настройки выравнивания.
На рисунке в некоторой степени проясняется то, как это работает в StackPanel:


Сверху представлено окно в минимальном размере. Кнопки имеют размер по 100 единиц каждая, и окно не может быть сужено, чтобы сделать их меньше. Если вы попытаетесь сжать окно от этой точки, то правая часть каждой кнопки будет усечена. (Такую возможность можно предотвратить применением свойства MinWidth к самому окну, так что окно нельзя будет сузить меньше минимальной ширины.)
При увеличении окна кнопки также растут, пока не достигнут своего максимума в 200 единиц. Если после этого продолжать увеличивать окно, то с каждой стороны от кнопок будет добавляться дополнительное пространство (как показано на нижнем рисунке).
В некоторых ситуациях может использоваться код, проверяющий, насколько велик элемент в окне. Свойства Height и Width в этом не помогут, т.к. отражают желаемые установки размера, которые могут не соответствовать действительному визуализируемому размеру. В идеальном сценарии элементам позволено менять размеры так, чтобы уместить свое содержимое, и тогда свойства Height и Width вообще устанавливать не надо. Узнать действительный размер, используемый при визуализации элемента, можно через свойства ActualHeight и ActualWidth. Однако помните, что эти значения могут меняться при изменении размера окна или содержимого элементов.
Окна с автоматически устанавливаемыми размерами
В данном примере присутствует один элемент с жестко закодированным размером: окно верхнего уровня, которое содержит в себе панель StackPanel (и все остальное внутри). По ряду причин жестко кодировать размеры окна по-прежнему имеет смысл:
- Во многих случаях требуется сделать окно меньше, чем диктует желаемый размер его дочерних элементов. Например, если окно включает контейнер с прокручиваемым текстом, нужно будет ограничить размер этого контейнера, чтобы прокрутка стала возможной. Не следует делать это окно чрезмерно большим, чтобы отпала необходимость в прокрутке, чего требует контейнер.
- Минимальные размеры окна могут быть удобны, но при этом не обеспечивать наиболее привлекательные пропорции. Другие размеры окна просто лучше выглядят.
- Автоматическое изменение размеров окна не ограничено размером области отображения на мониторе. В результате окно с автоматически установленным размером может оказаться слишком большим для просмотра.
Однако окна с автоматически устанавливаемым размером вполне допустимы, и они имеют смысл, когда конструируется простое окно с динамическим содержимым. Чтобы включить автоматическую установку размеров окна, удалите свойства Height и Width и установите свойство Window.SizeToContent в WidthAndHeight. Окно сделает себя достаточно большим, чтобы уместить все содержимое. Можно также позволить окну изменять свой размер только в одном измерении, используя для свойства SizeToContent значение Width или Height.
Практическое руководство. Автоматическое изменение размера окна в соответствии с размером содержимого
В этом примере показано, как установить свойство 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
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Окна
Ключевым элементом в системе графического интерфейса в WPF является окно, которое содержит все необходимые элементы управления. Окно в WPF представлено классом Window , который является производным от класса ContentControl. Поэтому окно является элементом управления содержимым, и как, к примеру, кнопка, может содержать в себе один дочерний элемент. Как правило, в его качестве выступает один из элементов компоновки, например, Grid.
Класс Window привносит ряд свойств, которые позволяют настроить окно приложения:
- AllowsTransparency : при значении true позволяет установить прозрачный фон окна
- Icon : представляет иконку, которая отображается в левом верхнем углу окна и в панели задач. Если иконка не установлена, то система будет использовать стандартную иконку по умолчанию.
- Top : устанавливает отступ окна приложения от верхней границы экрана
- Left : устанавливает отступ окна приложения от левой границы экрана
- ResizeMode : задает режим изменения размеров окна. Может принимать следующие значения:
- CanMinimize : окно можно только свернуть
- NoResize : у окна нельзя изменить начальные размеры
- CanResize : у окна можно изменять размеры
- CanResizeWithGrip : в правом нижнем углу окна появляется визуализация того, что у окна можно изменять размеры
- Width : автоматически масштабируется только ширина
- Height : автоматически масштабируется только высота
- WidthAndHeight : автоматически масштабируются высота и ширина
- Manual : автоматическое масштабирование отсутствует
- CenterOwner : если данное окно было запущено другим окном, то данное окно позиционируется относительно центра запустившего его окна
- CenterScreen : окно помещается в центре экрана
- Manual : позиция устанавливается вручную с помощью свойств Top и Left
- Maximized : раскрыто на весь экран
- Minimized : свернуто
- Normal : стандартное состояние
Жизненный цикл
В процессе работы окно в WPF проходит ряд этапов жизненного цикла, которые доступны нам через обработку событий класса Window:

- Initialized : это событие возникает при инициализации окна, когда у него устанавливаются все свойства, но до применения к нему стилей и привязки данных. Это общее событие для всех элементов управления в WPF, поэтому следует учитывать, что сначала возникают события вложенных элементов, а затем их контейнеров. То есть событие Initialized окна приложения генерируется только после того, как отработает событие Initialized для всех вложенных элементов.
- Loaded : возникает после полной инициализации окна и применения к нему стилей и привязки данных. После генерации этого события происходит визуализация элемента, и окно отображается на экране и становится видимым для пользователя
- Closing : возникает при закрытии окна
- Closed : возникает, когда окно становится закрытым
- Unloaded : возникает после закрытия окна при выгрузке всех связанных ресурсов из памяти
Соответственно, если нам надо выполнить некоторые действия при загрузке или при закрытии окна, мы можем обработать события Loaded и Closing/Closed. Например, запишем в текстовый лог события жизненного цикла:
using System; using System.Windows; using System.Windows.Media; using System.IO; namespace WindowApp < public partial class MainWindow : Window < string path = "log.txt"; public MainWindow() < InitializeComponent(); this.Loaded += MainWindow_Loaded; this.Closing += MainWindow_Closing; this.Closed += MainWindow_Closed; >private void MainWindow_Loaded(object sender, RoutedEventArgs e) < Log("Loaded"); >private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) < Log("Closing"); >private void MainWindow_Closed(object sender, EventArgs e) < Log("Closed"); >private void Log(string eventName) < using (StreamWriter logger = new StreamWriter(path, true)) < logger.WriteLine(DateTime.Now.ToLongTimeString() + " - " + eventName); >> > >