Содержание
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. Все элементы управления могут размещаться в строках и столбцах сетки. Элементы могут располагаться как в одной, так и нескольких строках или столбцах, а сами строки и столбцы могут имет как абсолютные, так и относительные или автоматические размеры.








