Главная » WPF » Модель слотов WPF

0

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

На  вычисление размеров  области,  отводимой  родителем  для  дочернего  эле# мента, влияют разные свойства, но не следует забывать и о пустых промежутках, разделяющих элементы.  Если  вам доводилось  работать  с CSS, то вы знакомы  с ящичной  моделью, в которой для каждого элемента определены  поля, отступы и границы. В WPF мы остановились на более простой модели, учитывающей ком# позиционную природу системы размещения.

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

Свойство Margin (поле) позволяет потомку оставить вокруг себя пустое пространство  – внутри слота, но вне содержимого. Свойства HorizontalAlignment и VerticalAlignment описывают,  как потомок  распорядится оставшимся в слоте пространством (выравнивание определяется относительно области,  из которой поля уже исключены).

Рис. 4.2. Выравнивание кнопок внутри панели

public class FrameworkElement : UIElement {

public HorizontalAlignment HorizontalAlignment { get; set; }

public Thickness Margin { get; set; }

public VerticalAlignment VerticalAlignment { get; set; }

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

}

На рис. 4.2 показаны два разных объекта StackPanel. Для верхней панели задана ориентация по вертикали (кнопки располагаются друг под другом сверху вниз),  а для нижней  – по горизонтали (кнопки располагаются одна за другой слева напра# во). Пунктирными линиями обозначены  границы  слотов, которые  панель  отвела каждому  дочернему  элементу.  С помощью  свойств  HorizontalAlignment и VerticalAlignment можно управлять тем, какую часть слота будет занимать элемент:

<StackPanel Orientation=’Vertical’ Background=’…’>

<Button HorizontalAlignment=’Center’>Center</Button>

<Button HorizontalAlignment=’Left’>Left</Button>

<Button HorizontalAlignment=’Right’>Right</Button>

<Button HorizontalAlignment=’Stretch’>Stretch</Button>

</StackPanel>

<StackPanel Orientation=’Horizontal’ Background=’…’>

<Button VerticalAlignment=’Center’>Center</Button>

<Button VerticalAlignment=’Top’>Top</Button>

<Button VerticalAlignment=’Bottom’>Bottom</Button>

<Button VerticalAlignment=’Stretch’>Stretch</Button>

</StackPanel>

Свойство  Margin  позволяет  задать поля вдоль каждой стороны слота или од# но значение для всех сторон. Как видно из рис. 4.3, поля могут быть и отрицатель# ными (пунктирными линиями снова обозначены  границы слотов):

Рис. 4.3. Задание полей для кнопок

<StackPanel Orientation=’Vertical’ Background=’…’>

<Button Margin=’0’ HorizontalAlignment=’Stretch’>No margin</Button>

<Button Margin=’5’ HorizontalAlignment=’Stretch’>5 all around</Button>

<Button Margin=’10,0,10,0’ HorizontalAlignment=’Stretch’>

10 on left and right</Button>

<Button Margin=’ 15,0,0,0’ HorizontalAlignment=’Stretch’> Negative on the left</Button>

</StackPanel>

На рис. 4.3 показана еще одна не такая заметная, но важная вещь: по умолчанию от# сечение не производится. Что это означает? Обратите внимание, что последняя кноп# ка выступает за границы родительской панели. В Win32 в этом случае выступающие части дочерних элементов по умолчанию отсекались; лишь в очень редких случаях по# томку разрешалось выйти за пределы родительского контейнера.  А еще реже удава# лось получить корректный результат, если потомок рисовал за пределами родителя.

В главе 1 уже отмечалось, что в WPF используется механизм композиции, при# чем элементы рисуются, начиная с самого отдаленного от зрителя (алгоритм худож# ника). Отсечение  – это дорогостоящая операция:  при рисовании каждого пикселя надо проверить,  попадает ли он внутрь области отсечения.  Достоинства отсечения проявляются при рисовании отдельно взятого элемента управления. В мире, где от# сечения нет, мы никогда не узнаем, что какой#то элемент пожелал что#то нарисовать за пределами отведенной ему области и тем самым испортил  нам всю картину.

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

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

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

Рис. 4.4. Три кнопки без применения преобразований

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

По теме:

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