Содержание
Grid
(Сетка) является, по-видимому, одним из самых популярных и часто используемы контейнеров WPF. По сути, этот контейнер работает как обычная таблица в которой элементы управления могут располагаться как в строках, так и в столбцах. Не зря при создании нового проекта WPF именно этот контейнер используется по умолчанию.
Пример «сеточного» макета
Рассмотрим следующий пример с использованием Grid
, чтобы получить общее представление об этом контейнере:
<Window x:Class="WpfApp2.MainWindow" 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:WpfApp2" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="2*"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="2*"/> <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> <Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Background="#FFCE2389"/> </Grid> </Window>
Результат работы показан на рисунке ниже:
Теперь рассмотрим, что было сделано в коде XAML. Для определения строк в сетке мы использовали свойство-коллекцию RowDefinitions
. Для описания каждой строки мы создали в коллекции элементы RowDefinition
и для каждого элемента прописали его высоту. Аналогичным образом мы создали три столбца, но здесь мы уже использовали свойство-коллекцию ColumnDefinitions
и поместили в него три элемента ColumnDefinition
, указав ширину столбца. В результате, мы получили сетку 3х3:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="2*"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="2*"/> <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> .... </Grid>
Далее, мы поместили в нашу сетку элемент Border
и указали для этого элемента толщину границы, её цвет, цвет заливки, а также два важных свойства: Grid.Column
и Grid.Row
, которые указывают в каком столбце и в какой строке (а в совокупности — в какой ячейке) должен располагаться элемент:
<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Background="#FFCE2389"/>
Так как в WPF, как и полагается, нумерация элементов коллекций начинается с нуля, то наш элемент Border
оказался в центральной ячейке наше сетки. Теперь можем запустить приложение и убедиться, что при любом изменении формы наш Border будет менять свое положение так, чтобы занимать центральную ячейку сетки.

Размеры элементов
Размеры элементов в WPF можно указывать как в абсолютных (что нежелательно), так и в относительных единицах измерения.
Единицы измерения абсолютных размеров
Размеры элементов в WPF можно задавать в следующих единицах измерения:
px (по умолчанию) |
независимые от устройства единицы измерения (1/96 дюйма на единицу) |
in |
дюймы (1in=96px) |
cm |
сантиметры (1cm = (96/2.54) px) |
pt |
точки (1pt=(96/72) px) |
Например, зададим такие размеры нашей сетки
<Grid> <Grid.RowDefinitions> <RowDefinition Height="0.5in"/> <RowDefinition Height="20pt"/> <RowDefinition Height="100px"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="10px"/> <ColumnDefinition Width="2in"/> <ColumnDefinition Width="30px"/> </Grid.ColumnDefinitions> .... </Grid>
Теперь мы получим следующую форму приложения:
При этом, при изменении размера окна, объект Border
не будет изменять своего положения и размера:
На рисунке видно, что правый край Border вообще ушел из поля зрения и интерфейс «поломался».
Автоматические размеры
Если вместо конкретных размеров указать в значениях свойств Height
и Width
значение Auto
, то размеры строк и столбцов будут рассчитываться в зависимости от их содержимого. Например, объявим размеры строк и столбцов нашей сетки автоматическими:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Background="#FFCE2389" Width="100" Height="100"/> </Grid>
Обратите внимание на то, что теперь у элемента Border
указаны его размеры. Так как только в средней ячейке (с координатами 1;1) находится элемент, то столбцы с номерами 0 и 2, а также строки с номерами 0 и 2 примут нулевой размер, а макет приложения будет следующим:
Относительные (пропорциональные) размеры
Для того, чтобы указать относительный размер, после числа ставится символ *
(звездочка). Чтобы понять как работают относительные размеры, зададим следующие значения для наших столбцов и строк:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="2*"/> <RowDefinition Height="3*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="2*"/> <ColumnDefinition Width="2*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> .... </Grid>
Теперь посмотрим как изменится вид нашей формы:
Элемент Border
теперь занимает ровно 1/3 от ширины сетки, но немного смещен по вертикали. Как рассчитываются относительные размеры? Рассмотрим на примере строк. Пусть у нас сетка имеет высоту 450
пикселей. Для строк заданы следующие размеры: 1+2+3 = 6
. Высота каждой строки будут рассчитываться следующим образом:
- 1 строка: 450*1/6 = 75 пикселей
- 2 строка: 450*2/6 = 150 пикселей
- 3 строка: 450*3/6 = 225 пикселей
Соответственно, когда мы меняем размер формы, то размеры строк и столбцов пересчитываются по их относительным размерам и интерфейс не «ломается».
Комбинированные размеры
Если необходимо, то мы можем комбинировать все типы размеров как нам будет угодно. Например, мы можем задать вот такие размеры строк:
<Grid.RowDefinitions> <RowDefinition Height="10pt"/> <RowDefinition Height="2*"/> <RowDefinition Height="3cm"/> </Grid.RowDefinitions>
В этом случае размер ширины или высоты элемента сетки будет рассчитываться следующим образом:
- от ширины/высоты сетки отнимается ширина/высота столбцов/строк с абсолютными или автоматическими размерами
- оставшееся место распределяется между столбцами/строками с пропорциональными размерами.
В приведенном выше примере с комбинированными размерами приложение примет следующий вид:
«Объединение» строк и столбцов сетки
Слово «объединение» взято в кавычки потому что, фактически, никакого объединения не происходит, однако мы можем помещать элемент не в одну, а несколько строк или столбцов как бы объединяя ячейки. Для этого используются два свойства: Grid.ColumnSpan
и Grid.RowSpan
. Рассмотрим использование этих свойств на примере нашего элемента Border
.
Элемент размещается в двух строках:
<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Background="#FFCE2389"/>
Результат:
Элемент размещается в двух столбцах:
<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Background="#FFCE2389"/>
Результат:
Комбинирование свойств Grid.ColumnSpan и Grid.RowSpan
<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2" Background="#FFCE2389"/>
Результат:
Итого
Сетка (Grid) — это наиболее популярный и функциональный контейнер для построения макета приложения в WPF. Все элементы управления могут размещаться в строках и столбцах сетки. Элементы могут располагаться как в одной, так и нескольких строках или столбцах, а сами строки и столбцы могут имет как абсолютные, так и относительные или автоматические размеры.