Главная » WPF » Размещение WPF

0

В главе 3 мы привели  обзор библиотеки  тех элементов  управления на плат# форме Windows Presentation Foundation, которые применяются для построения пользовательского интерфейса приложения. В серьезных приложениях одним элементом не обойтись, поэтому нужен способ позиционирования элементов.

Если  элементы  управления входят  во все ведущие  каркасы  для  разработки графических интерфейсов вот уже больше 15 лет, то идея управления размеще# нием появилась с запозданием.  Для  разработчиков на платформе Win32  разме# щение основано  на использовании простой  двумерной  системы координат  с на# чалом в левом верхнем углу окна. С другой стороны, в HTML#документах можно применять сочетание потока текста, таблиц и абсолютного позиционирования.

В WPF концепция размещения глубоко интегрирована во все элементы  уп# равления.  Механизм  размещения в WPF состоит из двух частей: контракта, описывающего,  как компонент  принимает  участие в размещении,  и набора реа# лизаций  этого контракта1. Никакого встроенного  размещения нет; все конкрет# ные способы размещения построены  на базе механизмов  расширяемости плат# формы.

Принципы размещения

Разработчики WPF хорошо понимали,  что управление  размещением  должно стать неотъемлемой частью системы. Мы ставили себе целью определить  единую систему размещения, которая  охватывала  бы все – от разбиения документов  на страницы  до традиционных пользовательских интерфейсов. В конце концов мы осознали, что создать единую монолитную  систему, пригодную для такого широ# кого спектра сценариев, невозможно2 (или, по крайней мере, очень трудно), и ре# шили перейти к модели композиции менеджеров  размещения. В результате  к за# даче размещения мы подошли так же, как к созданию библиотеки  элементов  уп# равления,  то есть разрешили вложенность менеджеров.

1  В этой главе не рассматривается один из важнейших компонентов размещения: текст. Тут возни) кают интересные вопросы, касающиеся разбиения на страницы, организации колонок и оптималь) ном для чтения представлении (к примеру, переносы и выравнивание). Размещение текста реали) зовано в виде расширения базовой модели. Подробно мы будем рассматривать его в главе 5.

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

При  таком  подходе самым  важным  казалось  определить,  как дочерний  эле# мент должен  взаимодействовать с родительским менеджером  размещения. Мы надеялись, что «контракт» между родителем и потомком позволит размещать лю# бой элемент управления в любом менеджере.

Контракт о размещении

Контракт о размещении определяет  способ взаимодействия между менедже# ром и дочерним элементом. Задача  в том, чтобы контракт  был как можно проще, но при этом позволял совместно  работать  различным реализациям менеджеров размещения. Хотя семантика  некоторых менеджеров  сложна и требует глубоких знаний  о дочерних элементах, команда разработчиков WPF полагала, что у всех реализаций менеджеров  должно быть нечто общее. Менеджер  должен уметь оп# ределять  размер каждого дочернего элемента  и сообщать своему родительскому менеджеру  о собственном  предпочтительном размере.  В итоге  все  сводится  к двум простым идеям: адаптация к содержимому  и двухэтапное  размещение.

Адаптация к содержимому

Как следует из названия,  идея адаптации менеджера к содержимому заклю# чается в том, чтобы определить  собственный  размер в зависимости от содержи# мого. Эта концепция применяется на всех уровнях пользовательского интерфей# са: окна могут подгонять свой размер под находящиеся в них элементы, кнопки – подстраиваться под надписи на них, а текстовые поля – изменять размер так, что# бы поместились все символы.  Чтобы  реализовать идею на практике,  менеджер должен спросить у каждого элемента, какой размер тот предпочитает.

Двухэтапное размещение

Предпочтительный размер элемента управления определяется в два этапа: из# мерение  и установка.  Эта модель двухэтапного  размещения дает и родителю,  и потомку шанс достичь соглашения об окончательном размере элемента.

На этапе измерения мы обходим все дерево отображения и запрашиваем у каждо# го элемента  его предпочтительный размер  с учетом ограничения. Элемент  должен вернуть реальный размер, даже если ограничения допускают бесконечную величину (например, при размещении в контейнере  с прокруткой). После того как все элемен# ты измерены, мы приступаем  к этапу установки, в ходе которого родитель требует от каждого дочернего элемента, чтобы тот установил определенный размер и положение.

Эта модель позволяет  родителю и потомку договариваться о потребном месте на экране. Обсуждаются три представляющих интерес размера: располагаемый, предпочтительный и фактический. Располагаемый размер (available  size) – это начальное ограничение, используемое на этапе измерения, как правило макси# мальная область, которую родитель готов предоставить своему потомку. Пред почтительный размер (desired  size) – это размер, который  желал бы установить потомок. Фактический размер (actual size) – это тот окончательный размер, ко# торый родитель  назначает  потомку. В идеальном  мире эти величины  удовлетво# ряли бы следующему соотношению:

desiredSize <= actualSize <= availableSize

В иерархии  классов  WPF менеджер  размещения представлен  базовым  клас# сом UIElement. Та часть объектной  модели UIElement, которая  относится  к ме# неджеру размещения, довольна проста. Методы Measure, MeasureCore, Arrange и ArrangeCore реализуют  два этапа размещения, а свойство Visibility  говорит, дол# жен ли элемент отображаться и учитываться при размещении3:

public class UIElement : Visual {

public bool Visibility Visibility { get; set; }

public void Arrange(Rect finalRect);

protected virtual void ArrangeCore(Rect finalRect);

public void Measure(Size availableSize);

protected virtual Size MeasureCore(Size availableSize);

}

Рис. 4.1. Видимая, свернутая и скрытая кнопки. Обратите внимание, что для свернутой кнопки место вообще не отводится.

Свойство  Visibility  позволяет  задать три способа участия  дочернего элемента в размещении.  По умолчанию  оно равно  Visible, то есть все элементы  видимы; они отображаются и занимают  место на экране.  Если  значение  этого свойства равно Hidden,  то элемент скрыт (не отображается, но занимает место), а если Collapsed, то элемент свернут (не отображается и не занимает места). На рис. 4.1 изображены три кнопки  с разными  значениями свойства  Visibility.  Пунктирная рамка показывает,  какое место занимает элемент.

Базовый контракт  о размещении сформулирован максимально гибко, чтобы не налагать излишних ограничений на реализацию.  На его основе оказалось  воз# можно реализовать развитые  типографические макеты  и самые разные  двумер# ные способы размещения4. Эта базовая  модель – один из самых важных  строи# тельных блоков; при решении задач о размещении на плоскости выявилось нема# ло общих паттернов.

3  Смысл двух наборов методов в том, чтобы отделить методы, который нужно переопределить при реализации менеджера размещения (ArrangeCore и MeasureCore), от открытых методов (Arrange и Measure). Например, при реализации панели размещения для дочерних элементов всегда должны вызываться методы Arrange и Measure; методы же ArrangeCore и MeasureCore никогда не вызываются явно. Решение о таком разделении было принято для того, чтобы сис) тема могла выполнять какие)то нетривиальные действия (скажем, кэширование или обновле) ние экрана) на этапах измерения и установки.

4  Размещения в трехмерном пространстве — очень интересная тема, но в настоящее время ее луч)

ше оставить теоретикам.

Согласованное размещение

Чтобы упростить  реализацию менеджеров  размещения, согласованных с эти# ми паттернами,  в WPF имеется слой поверх контракта  о размещении.  Свойства, управляющие общими паттернами  размещения, определены в пространстве имен System.Windows.FrameworkElement.

Пожалуй,  самым общим из всех выявленных нами паттернов, является поня# тие ограничения на размещение.  При построении  пользовательского интерфейса часто бывает необходимо задать минимальный и максимальный размер или даже указать конкретный размер (то есть запретить  адаптацию под содержимое).

Ограничения на размещение

Для задания ограничений на размещение в классе FrameworkElement определе#

но шесть свойств: MinWidth, MinHeight, MaxWidth, MaxHeight, Width и Height:

public class FrameworkElement : UIElement {

public double Height { get; set; } public double MaxHeight { get; set; } public double MaxWidth { get; set; } public double MinHeight { get; set; } public double MinWidth { get; set; } public double Width { get; set; }

// другие члены FrameworkElement …

}

Обычно свойства Width и Height  явно не задаются, поскольку  иначе адапта# ция под размер содержимого была бы вообще отключена. С другой стороны, свойства  MinWidth, MinHeight, MaxWidth и MaxHeight позволяют  наложить ограничения на  размещение,  не запрещая  адаптацию.  Например, вместо  того чтобы указывать ширину кнопки, мы можем присвоить свойству MinWidth предпочтительную ширину. Если будет задана очень длинная  надпись, то кноп# ка расширится, так чтобы вместить ее целиком, но обычно будет иметь предпоч# тительный размер.

Свойства  ActualHeight и ActualWidth можно  только  читать, они позволяют узнать  фактический размер  элемента.  Отметим,  что  их  значения   достоверны только по завершении обоих этапов размещения (измерения и установки).

Выбор типа данных  свойств  Width и Height  стал предметом  горячих  споров при разработке WPF. Проблема была в том, как поступать с процентами и автома# тическим  выбором  размера5.  Когда задается  автоматический выбор ширины  или высоты, система размещения понимает, что размер элемента следует адаптировать под содержимое. Учитывая, что такое поведение подразумевается по умолчанию, авторы решили, что отсутствие явно заданной ширины или высоты будет означать автоматический выбор6. Но придумать, как быть с заданием размеров в процентах,

5  Менее серьезная проблема была связана с тем, как обращаться с физическими единицами изме)

рения (дюймами, сантиметрами и т.д.). Но поскольку все линейные размеры в WPF выражаются в

1/96 дюйма, то для поддержки произвольной единицы достаточно тривиальной арифметики.

6  Можно также использовать значение Double.NaN.

оказалось гораздо труднее. Для некоторых элементов управления (например, Grid или Table) понятие  процентной доли естественно. Другие (например, Canvas) поддержать его не могут в принципе  (ниже мы увидим, почему).

Источник: К. Андерсон  Основы  Windows Presentation Foundation. Пер. с англ. А. Слинкина — М.: ДМК Пресс, 2008 — 432 с.: ил.

По теме:

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