Группы с общими размерами
48WPF --- Основа WPF --- Группы с общими размерами
Grid содержит коллекцию строк и колонок, размер которых устанавливается явно, пропорционально или на основе размеров их дочерних элементов. Существует только один способ изменить размер строки или колонки — приравнять его к размеру другой строки или колонки. Это выполняется с помощью средства, которое называется группы с общими размерами (shared size groups).
Цель таких групп — поддержание согласованности между различными частями пользовательского интерфейса. Например, размер одной колонки может быть установлен в соответствии с ее содержимым, а размер другой колонки — в точности равным размеру первой. Однако реальное преимущество групп с общими размерами заключается в обеспечении одинаковых пропорций различным элементам управления Grid.
Чтобы понять, как это работает, рассмотрим пример, в котором окно оснащено двумя объектами Grid — один в верхней части окна (с тремя колонками) и один в его нижней части (с двумя колонками). Размер левой крайней колонки первого Grid устанавливается пропорционально ее содержимому (длинной текстовой строке). Левая крайняя колонка второго Grid имеет в точности ту же ширину, хотя имеет меньшее содержимое. Дело в том, что они входят в одну размерную группу. Независимо от того, какое содержимое вы поместите в первую колонку первого Grid, первая колонка второго Grid останется синхронизированной.
<Grid Grid.IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" SharedSizeGroup="SomeText"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label>Длинный текст</Label>
<Label Grid.Column="1">Другой текст</Label>
<TextBlock Grid.Column="2" Padding="5">Элемент TextBlock</TextBlock>
</Grid>
<Label Grid.Row="1">Текст между двумя элементами Grid</Label>
<Grid Grid.Row="2" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" SharedSizeGroup="SomeText"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label>Текст</Label>
<TextBlock Grid.Column="1" Padding="5">TextBlock in Grid2</TextBlock>
</Grid>
</Grid>
Как демонстрирует этот пример, колонки с общими размерами могут принадлежать к разным элементам Grid. В этом примере верхний Grid имеет на одну колонку больше и потому оставшееся пространство в нем распределяется иначе. Аналогично колонки с общими размерами могут занимать разные позиции, так что можно создать отношение между первой колонкой одного Grid и второй колонкой другого. И очевидно, что колонки при этом могут иметь совершенно разное содержимое.
Когда применяется группа с общими размерами, это все равно, как если бы создавалось одно определение колонки (или строки), используемое в более чем одном месте. Это не просто однонаправленная копия одной колонки в другую. В этом можно убедиться, изменив в предыдущем примере содержимое разделенной колонки второго Grid. Теперь колонка в первом Grid будет удлинена для сохранения соответствия:
Можно даже добавить GridSplitter к одному из объектов Grid. Когда пользователь будет изменять размер колонки в одном Grid, то соответствующая разделенная колонка из второго Grid также будет синхронно менять свой размер.
Создать группы с общими размерами просто. Понадобится лишь установить свойство SharedSizeGroup в обеих колонках, используя строку соответствия. В текущем примере обе колонки используют группу по имени SomeText.
Осталось упомянуть еще одну деталь. Группы с общими размерами не являются глобальными для всего приложения, потому что более одного окна могут непреднамеренно использовать одно и то же имя. Можно предположить, что группы с общими размерами ограничены текущим окном, но на самом деле платформа WPF еще более строга в этом отношении. Чтобы разделить группу, необходимо явно установить присоединенное свойство Grid.IsSharedSizeScope в true в контейнере высшего уровня, содержащем объекты Grid, который имеет колонки с общими размерами. В текущем примере верхний и нижний Grid входят в другой Grid, предназначенный для этой цели, хотя столь же просто можно применить другой контейнер, такой как DockPanel или StackPanel.
Для синхронизации отдельных Grid с заголовками колонок можно было бы использовать группу с общими размерами. Ширина каждой колонки может быть затем определена ее содержимым, которое разделит заголовок. Допускается даже поместить GridSplitter в заголовок, и тогда пользователь сможет перетаскивать его для изменения размера заголовка и всей лежащей ниже колонки.