Главная » Silverlight » Двухэтапный процесс размещения

0

В объекте любой панели автоматически применяется один и тот же двухэтапный процесс установки размеров и размещения дочерних элементов. На первом этапе вы­полняется вычисление размеров дочерних элементов и характерных расстояний, а на втором — собственно размещение дочерних элементов. Два этапа необходимы потому, что панель должна учесть требования всех дочерних элементов, прежде чем распреде­лить доступное пространство.

Добавить код, управляющий этими двумя этапами, можно, переопределив методы MeasureOverride() и ArrangeOverride(), определенные в классе FrameworkElement платформы Silverlight. Указанные методы замещают логику методов MeasureCore () и ArrangeCore (), определенных в классе UIElement. Последние два метода для кода приложения недоступны и переопределить их невозможно.

Метод MeasureOverride ()

Первый этап — вычисление пространства, необходимого каждому дочернему элемен­ту, с помощью метода MeasureOverride (). Однако даже в методе MeasureOverride () до­черним элементам не предоставлено безграничное пространство. Как минимум, они ограни­чены пространством, доступным для панели. При необходимости их можно ограничить еще более жестко. Например, панель Grid с двумя пропорциональными строками предостав­ляет дочерним элементам половину доступной высоты. Панель StackPanel предоставляет первому элементу все доступное пространство, второму — все, что осталось после разме­щения первого, третьему — все, что осталось после размещения первых двух, и т.д.

Каждая реализация MeasureOverride () проходит в цикле по коллекции дочерних элементов и вызывает для каждого из них метод Measure (). Ему передается объект Size, определяющий максимально доступное пространство для дочернего элемента управле­ния. В конце метода MeasureOverride () панель возвращает пространство, необходимое для отображения всех дочерних элементов, и желательные размеры элементов.

Ниже приведена базовая структура метода MeasureOverride () без специфических операторов установки размеров.

protected override Size MeasureOverride(Size constraint)

{

// Проход по всем дочерним элементам

foreach (UIElement element in this.Children) {

// Вычисление пространства, необходимого текущему

// дочернему элементу с учетом ограничений availableSize

Size availableSize = new Size (…);

element.Measure(availableSize);

// Теперь можно извлечь запрошенный

// размер из element.DesiredSize

}

// Вычисление пространства, необходимого для панели; // оно будет использовано для установки // свойства DesiredSize панели return new Size (…);

}

Метод Measure () не возвращает значения. После вызова метода Measured через дочерний элемент, запрошенный размер предоставляется в свойстве DesiredSize до­чернего элемента. Эту информацию можно использовать для размещения следующих дочерних элементов и для вычисления общего пространства, необходимого панели.

Вызов метода Measure () обязателен для каждого дочернего элемента, даже если вы не планируете ограничивать его размеры или применять его свойство DesiredSize. Многие элементы не отображаются на экране, пока через них не будет вызван метод Measure (). Если нужно предоставить дочернему элементу возможность занять все свободное про­странство, которое он пожелает, передайте в качестве параметра объект Size со значения­ми Double. Positivelnf inity для обеих координат (обычно такой способ используется для элемента прокрутки ScrollViewer, поскольку он должен охватывать все содержимое). При значении Positivelnfinity дочерний элемент возвращает пространство, необходимое для его содержимого. В противном случае он возвращает одно из двух значений (меньшее из двух): либо пространство, необходимое для содержимого, либо доступное пространство.

В конце процесса вычисления контейнер должен возвратить свой желаемый размер. Для простой панели ее желаемый размер вычисляется на основе желаемых размеров каждого дочернего элемента.

Примечание. В качестве желаемого размера панели можно просто возвратить ограничение, переданное методу MeasureOverride (). На первый взгляд это кажется прекрасным способом получения всего доступного пространства, однако такой способ приведет к серьезным проблемам, если в качестве одной или обеих координат передается объект Size со значениями Double. Positivelnfinity (объект Positivelnfinity в данном случае означает "возьмите все пространство, сколько захотите"). В качестве ограничения допустимо бесконечное значение, однако в качестве размера оно недопустимо. Надстройка Silverlight не сможет понять, какими должны быть размеры элемента. Кроме того, не следует запрашивать больше пространства, чем необходимо. Лишнее пространство заставит следующие элементы, размещаемые после панели, переместиться вниз, в результате чего будет создано пустое пространство на экране.

Внимательные читатели уже, наверное, заметили сходство между мето­дами Measure)), вызываемыми через каждый дочерний элемент, и методами MeasureOverride (), определяющими первый этап обработки панели. Фактически метод Measure () запускает метод MeasureOverride (). Следовательно, если контейнеры вложе­ны друг в друга, то при вызове Measure () вы получите общий размер, необходимый для внешнего контейнера и всех его дочерних элементов.

Одна из причин того, что вычисление пространства должно выполняться в два эта­па, состоит в необходимости учитывать внешние полоски. При вызове метода Measure () он получает общее доступное пространство, а при вызове MeasureOverride () доступное пространство автоматически уменьшается для учета внешних полосок (естественно, если не передано бесконечное значение размера).

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

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