Главная » Разработка для Windows Phone 7 » Клон Grid с одной ячейкой

0

Простейшей панелью является Grid, который не содержит ни строк, ни столбцов. Такие Grid называют «Grid с одной ячейкой». Мы уже рассматривали использование Grid с одной ячейкой на примере ContentPanel. Как было показано, в Grid могут располагаться несколько дочерних элементов, но они перекрывают друг друга.

Продублируем функциональность Grid с одной ячейкой, создав класс SingleCellGrid (Сетка с одной ячейкой).

В новом проекте под именем SingleCellGridDemo (Демонстрация сетки с одной ячейкой) щелкнем правой кнопкой имя проекта, выберем в меню Add и New Item, затем выберем в диалоговом окне Class и назовем его SingleCellGrid.cs. В созданном файле убедимся, что класс является открытым и наследуется от Panel.

Проект Silverlight: SingleCellGridDemo Файл: SingleCellGrid.cs (фрагмент)

namespace SingleCellGridDemo {

public class SingleCellGrid : Panel {

}

}

Как все панели, этот класс перегружает два метода: MeasureOverride и ArrangeOverride. Рассмотрим первый из них:

Проект Silverlight: SingleCellGridDemo Файл: SingleCellGrid.cs (фрагмент)

protected override Size Measure0verride(Size availableSize) {

Size compositeSize = new Size();

foreach (UIElement child in Children) {

child.Measure(availableSize);

compositeSize.Width = Math.Max(compositeSize.Width, child.DesiredSize.Width);

compositeSize.Height = Math.Max(compositeSize.Height,

child.DesiredSize.Height); }

return compositeSize;

}

В MeasureOverride передается параметр availableSize (Доступный размер) типа Size. Эта структура имеет два свойства, Width и Height, типа double. Это размер, который панель получает от своего родительского элемента. Один или оба из этих размеров могут быть бесконечными.

Метод MeasureOverride выполняет две фундаментальные задачи.

Первая – вызов метода Measure всех дочерних элементов. Выполнение этой операции имеет важнейшее значение, в противном случае потомок не будет иметь размера и не будет отображен на экране. MeasureOverride практически всегда выполняет эту задачу путем перебора коллекции Children с помощью цикла foreach.

Вторая задача метода MeasureOverride – возвратить желаемый размер панели. В данном методе MeasureOverride этот размер сохраняется в переменной compositeSize (Совокупный размер). Данный размер должен иметь конечное неотрицательное значение. Метод MeasureOverride не может возвратить аргумент availableSize с предположением, что ему требуется все предлагаемое пространство, потому что аргумент availableSize может содержать бесконечные значения размеров.

На момент вызова метода MeasureOverride аргумент availableSize уже скорректирован должным образом. Если для панели задано свойство Margin, это поле не входит в availableSize. Если для панели задано любое из свойств Width, MinWidth (Минимальная ширина), MaxWidth (Максимальная ширина), Height, MinHeight (Минимальная высота) или MaxHeight (Максимальная высота), их значения ограничивают доступный размер.

Обе задачи MeasureOverride обычно выполняются совместно. Панель вызывает метод Measure всех дочерних элементов и предлагает каждому из них доступный размер. Этот размер может быть бесконечным. То какой аргумент Size передается в метод Measure, зависит от парадигмы конкретной панели. В данном случае SingleCellGrid предлагает каждому своему дочернему элементу собственный availableSize:

child.Measure(availableSize);

Панель позволяет каждому дочернему элементу существовать на одном пространстве с собой. Нет никакой проблемы в том, если этот аргумент availableSize определяет бесконечные размеры.

По завершении выполнения метода Measure свойство DesiredSize дочернего элемента задано и имеет действительное значение. Таков механизм определения желаемого размера дочернего элемента его родителем. Полученное значение свойства DesiredSize вычисляется методом Measure дочернего элемента после вызова собственного метода MeasureOverride, который, возможно, опрашивал о желаемых размерах собственные дочерние элементы. Методу MeasureOverride нет необходимости беспокоиться о значениях Margin или явно заданных Width и Height. Для этого есть метод Measure, который все учтет и настроит DesiredSize соответствующим образом. Например, если для дочернего элемента задано свойство Margin, DesiredSize будет включать это дополнительное поле.

Приведем некоторые примеры. Метод MeasureOverride элемента TextBlock возвращает размер текста, отображаемого конкретным шрифтом. Метод MeasureOverride элемента Image возвращает исходные размеры растрового изображения в пикселах. Метод MeasureOverride элемента Ellipse возвращает нулевой размер.

Свойство DesiredSize всегда имеет конечное значение. Метод MeasureOverride в SingleCellGrid определяет максимальный размер на основании значений свойств DesiredSize всех дочерних элементов и сохраняет его в локальной переменной compositeSize:

compositeSize.Width = Math.Max(compositeSize.Width, child.DesiredSize.Width); compositeSize.Height = Math.Max(compositeSize.Height, child.DesiredSize.Height);

Этот размер отражает самую большую ширину и высоту, необходимые для размещения всех дочерних элементов.

ArrangeOverride – второй обязательный метод наследуемого от Panel класса. Рассмотрим, как он описан в классе SingleCellGrid:

Проект Silverlight: SingleCellGridDemo Файл: SingleCellGrid.cs (фрагмент)

protected override Size Arrange0verride(Size finalSize) {

foreach (UIElement child in Children) {

child.Arrange(new Rect(new Point(), finalSize));

}

return base.Arrange0verride(finalSize);

}

Метод принимает аргумент finalSize (Окончательный размер). Это область, предоставленная панели его родительским элементом. Она всегда имеет конечные размеры.

Задача метода ArrangeOverride – скомпоновать дочерние элементы в предоставленной области. Это осуществляется путем перебора всех дочерних элементов и вызова метода Arrange каждого из них. Метод Arrange принимает обязательный аргумент типа Rect. Это прямоугольник, который определяется объектом Point, указывающим на верхний левый угол, и объектом Size, обозначающим высоту и ширину. Обычно это единственное появление Rect в процессе компоновки. Rect задает и местоположение дочернего элемента относительно верхнего левого угла родительского элемента, и его размер.

В данном конкретном случае всем дочерним элементам задан размер finalSize, такой же как размер самой панели, и все они помещены в верхний левый угол панели.

Если вы думаете, что размер, передаваемый в Arrange, должен быть DesiredSize дочернего элемента, это не так (по крайней мере не для этой конкретной панели). Очень часто значение finalSize больше, чем DesiredSize дочернего элемента. (Экстремальным случаем является Ellipse, для которого DesiredSize равен нулю.) Вот как в методе Arrange дочернего элемента настраиваются значения HorizontalAlignment и VerticalAlignment. В SingleCellGrid при вызове метода Arrange дочернего элемента в него передается finalSize:

child.Arrange(new Rect(new Point(), finalSize));

Метод Arrange сравнивает этот размер с собственным DesiredSize дочернего элемента и затем вызывает метод ArrangeOverride дочернего элемента, передавая в него размер и положение, скорректированные на основании параметров HorizontalAlignment и VerticalAlignment. Так Ellipse получает ненулевой размер, даже если его DesiredSize равен нулю.

Метод ArrangeOverride практически всегда возвращает аргумент finalSize, который содержит значение, возвращенное методом базового класса Panel.

Теперь протестируем все это. Файл MainPage.xaml в проекте SingleCellGridDemo должен ссылаться на этот пользовательский класс. В корневом элементе описание пространства имен XML связывает имя «local» (локальный) с пространством имен .NET, используемым проектом:

xmlns:local="clr-namespace:SingleCellGridDemo"

В файле MainPage.xaml SingleCellGrid помещается в сетку для содержимого и затем заполняется все теми же четырьмя элементами, с которыми мы работали в первых двух приложениях данной главы:

Проект Silverlight: SingleCellGridDemo Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <local:SingleCellGrid>

<TextBlock Text="TextBlock aligned at right bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" />

<Image Source="Images/BuzzAldrinOnTheMoon.png" />

<Ellipse Stroke="{StaticResource PhoneAccentBrush}" StrokeThickness="2 4" />

<TextBlock Text="TextBlock aligned at left top" HorizontalAlignment="Left" VerticalAlignment="Top" /> </local:SingleCellGrid> </Grid>

Данное приложение обеспечивает абсолютно такое же отображение элементов, как и приложение GridWithFourElements.

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии