Контролы - контейнеры
Сегодня поговорим о контролах, которые отвечают за группирование и расположение других контролов. К ним относятся Canvas, Grid, StackPanel. У каждого есть свои индивидуальные особенности. Соответственно мы используем каждый из них в конкретной ситуации. Контейнеры позволяет нам создавать некую структуру расположения элементов на нашей форме. Сочетания контейнеров и вложение их один в другой позволяет нам добиться определенного взаиморасположения и разбиения формы на определенные логические блоки. Ну и конечно без использования контейнеров мы не сможем расположить не один дочерний контрол.
Canvas
Canvas – наиболее часто используемый контейнер, представляет из себя прямоугольную форму. Имеет задаваемую высоту (Height) и ширину (Width). Может располагаться как на форме UserControl - а, так и в других контейнерах или на Canvas – е. Canvas – наиболее простой контейнер, который позволяет абсолютно располагать дочерние элементы.
Код XAML :
<UserControl xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="LayoutControls.Page" Width="400" Height="400"> <Canvas x:Name="LayoutRoot" Background="AliceBlue" > </Canvas> </UserControl>
Обычно рутовому (главному) контейнеру ширину и высоту не задают, и он принимает ширину и высоту всего UserControl – а. После добавления дочерних элементов на Canvas они приобретают свойства Canvas.Left и Canvas.Top. Эти свойства указывают абсолютные координаты дочерних элементов относительно контейнера. Отсчет координат идет относительно левого верхнего угла. Приведем пример расположения элемента
Код XAML :
<TextBox Text="test" Background="Aqua" Foreground="Red" Height="50" Width="100" Canvas.Left="100" Canvas.Top="100" />
Добавим еще несколько элементов, а также другой контейнер. Как видим, контейнер тоже приобретает свойства Canvas.Left и Canvas.Top. После его вложения в другой контейнер.
Код XAML:
<Canvas x:Name="LayoutRoot" Background="AliceBlue" > <TextBox x:Name="Text 1" Text="test" Background="Aqua" Foreground="Red" Height="50" Width="100" Canvas.Left="50" Canvas.Top="50" /> <TextBox x:Name="Text 2" Text="test" Background="Aqua" Foreground="Red" Height="50" Width="100" Canvas.Left="160" Canvas.Top="50" /> <Button x:Name="Button 1" Content="test" Background="Aqua" Foreground="Red" Height="50" Width="100" Canvas.Left="160" Canvas.Top="150" /> <Canvas x:Name="LayoutRoot 1" Background="Red" Width="100" Height="50" Canvas.Left="50" Canvas.Top="150" /></Canvas>
Все элементы расположены абсолютно. Таким образом, мы можем точно управлять место положением наших элементов формы.
StackPanel
StackPanel – Контрол контейнер, который используется в случае, когда нам необходимо, чтобы дочерние элементы шли один за другим, например в виде списка или каких либо последовательно используемых элементов.
Код XAML:
<UserControl xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="LayoutControls.Page" Width="400" Height="400"> <StackPanel Background="AntiqueWhite"> </StackPanel> </UserControl>
Далее попробуем добавить наши элементы из предыдущего примера. Чтобы элементы не залипали друг другу зададим каждому свойство margin – 5.
Код XAML:
<StackPanel Background="AntiqueWhite"> <TextBox x:Name="Text 1" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="100" /> <TextBox x:Name="Text 2" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="100" /> <Button x:Name="Button 1" Content="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="100" /> <Canvas x:Name="LayoutRoot 1" Background="Red" Margin="5" Width="100" Height="50" /> </StackPanel>
Как вы видите, элементы выстраиваются один за другим, по умолчанию ориентация их выстраивания вертикальная. Также как и Canvas StackPanel позволяет включать в себя другие контейнеры. Установим свойство Orientation на Horizontal и немного уменьшим размер наших элементов.
Код XAML :
<StackPanel Background="AntiqueWhite" Orientation="Horizontal"> <TextBox x:Name="Text 1" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" /> <TextBox x:Name="Text 2" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" /> <Button x:Name="Button 1" Content="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" /> <Canvas x:Name="LayoutRoot 1 " Background="Red" Margin="5" Width="50" Height="50" /> </StackPanel>
Наши элементы расположились один за другим горизонтально.
Grid
Grid – табличная форма представления контейнера. Мы можем разметить нашу форму на определенное количество столбцов и рядов, и распологать наши элементы в определенных ячейках. Для начала создадим таблицу с тремя столбцами и тремя рядами. Для этого нам необходимо создать обяъвление для рядов и столбцов, и в каждом объявлении создать по три столбца и три ряда. Чтобы нам было видно как мы разбили нашу форму установим у Grid свойство ShowGridLines="True". Посмотрим что у нас вышло:
Код XAML:
<UserControl xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="LayoutControls.Page" Width="300" Height="300"> <Grid Background="Beige" ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="100" /> <RowDefinition Height="100" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> </Grid> </UserControl>
Теперь попробуем добавить наши элементы из предыдущих примеров. Для того чтобы указать место расположения элементов нам необходимо указать колонку и ряд, в который мы хотим поместить элемент, для этого задаем свойства Grid.Row и Grid.Column, которые появляются после добавления элементов в наш Grid. Отсчет колонок и рядов начинается с 0. Если не указана никакая колонка, то по умолчанию элементы будут отображены в левой верхней колонке, откуда начинается отсчет колонок.
Код XAML:
<UserControl xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="LayoutControls.Page" Width="300" Height="300"> <Grid Background="Beige" ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="100" /> <RowDefinition Height="100" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> <Border Grid.Row="1" Grid.Column="0" Background="Azure" BorderThickness="10" CornerRadius="15" > </Border> <TextBox x:Name="Text 1" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" Grid.Row="1" Grid.Column="1" /> <TextBox x:Name="Text 2" Text="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" Grid.Row="2" Grid.Column="2" /> <Button x:Name="Button 1" Content="test" Margin="5" Background="Aqua" Foreground="Red" Height="50" Width="50" Grid.Row="2" Grid.Column="0" /> <Canvas x:Name="LayoutRoot 1 " Background="Red" Margin="5" Width="50" Height="50" Grid.Row="0" Grid.Column="0" /> </Grid> </UserControl>
Вот что у нас получилось. Если брать в сравнение построение таблиц, например, в том же HTML, то здесь взят совершенно другой принцип и с одной стороны он кажется совсем неудобным, но для SilverLight построение таблиц в таком виде вполне разумно, и в будущем вы привыкните к нему и Вам покажется это все очень простым.
Как вы заметили я добавил Элемент Border, в котором я изобразил, как можно задавать границы таблицы их толщину и радиус закругления.
Вот так выглядят контейнеры SilverLight. Надеюсь, эта статья помогла вам разобраться в их особенностях, и вы попробуете создать свои интересные шаблоны с помощью контейнеров.
Прилагаю тестовый проект, там ничего особенного нет. Особой красоты я не старался добиться, просто хотел показать пример разметки с помощью контейнеров
Пример использования контейнеров
Popularity: 54% [?]






Сентябрь 2nd, 2008 at 23:54
Привет.
Хорошая статья. Но этого мне мало, как в коде узнать абсолютные координаты контролов относительно страницы?
Октябрь 28th, 2008 at 17:03
[...] http://silverlightru.net/kontroly-kontejnery Published окт 28 2008, 09:03 by admin | [Edit Post] Помечено как: Блог, [...]
Октябрь 28th, 2008 at 18:26
[...] http://silverlightru.net/kontroly-kontejnery Published окт 19 2008, 01:26 by admin | [Edit Post] Помечено как: Блог, [...]
Октябрь 29th, 2008 at 03:20
alixachev - все очень просто, на самом деле любая страница содержит рутовый элемент например Canvas, Grid. соотвественно чтобы разместить элементы на этих контейнерах, надо у элемента указать так называемые Dependecy property. И так допустим у нас есть элемент которы лежит на Canvas - е. Пусть это будет TextBlock (MyText).
В коде пишем следующее:
MyText.GetValue(Canvas.TopProperty); //получаем координаты относительно верхней границы контейнера
MyText.GetValue(Canvas.LeftProperty);//получаем координаты относительно левой границы контейнера
MyText.GetValue(Grid.RowProperty); //получаем строку
MyText.GetValue(Grid.CollumnProperty); //получаем колонку