Контейнеры в WPF. Grid (сетка)

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

Grid
Элемент 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>

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

  1.  от ширины/высоты сетки отнимается ширина/высота столбцов/строк с абсолютными или автоматическими размерами
  2. оставшееся место распределяется между столбцами/строками с пропорциональными размерами.

В приведенном выше примере с комбинированными размерами приложение примет следующий вид:

«Объединение» строк и столбцов сетки

Слово «объединение» взято в кавычки потому что, фактически, никакого объединения не происходит, однако мы можем помещать элемент не в одну, а несколько строк или столбцов как бы объединяя ячейки. Для этого используются два свойства: Grid.ColumnSpan и Grid.RowSpan. Рассмотрим использование этих свойств на примере нашего элемента Border.

Элемент размещается в двух строках:

<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Background="#FFCE2389"/>

Результат:

Grid.RowSpan

Элемент размещается в двух столбцах:

<Border BorderBrush="Blue" BorderThickness="1" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Background="#FFCE2389"/>

Результат:

Grid.ColumnSpan

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

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии