Модель содержимого элементов управления
87Expression Blend --- Графические интерфейсы --- Модель содержимого элементов управления
В первом примере проекта, рассматриваемом в этом разделе, основное внимание уделяется такому заслуживающему особого внимания компоненту прикладных интерфейсов API на платформах WPF и Silverlight, как модель содержимого элементов управления.
В этой модели под термином содержимое подразумевается то, что обычно служит для заполнения внутренней части элемента управления графического пользовательского интерфейса. В частности, содержимым для типичного элемента управления типа Button являются текстовые данные надписи на кнопке, например, ОК, Отмена, Предъявить и т.п.
Для некоторых элементов управления графического пользовательского интерфейса может быть достаточно самого простого фрагмента текста, тем не менее на платформах WPF и Silverlight допускается определение намного более сложного содержимого.
В частности, можно определить элемент управления типа Button с оживляемой стрелкой и отображаемым фрагментом текста в качестве содержимого. Для определения сложного внутреннего содержимого в среде Expression Blend IDE предоставляются соответствующие инструменты, хотя их применение в подобных целях может оказаться не вполне очевидным. Для того чтобы разобраться в этом вопросе, начните, как всегда, с создания нового проекта приложения WPF, присвоив ему имя BlendControlContent.
Найдите на панели Tools или в библиотеке ресурсов элемент управления типа Button и расположите один его экземпляр у верхнего края монтажного стола визуального конструктора главного окна (объекта типа Window). Как только вы выберете этот элемент управления на монтажном столе, в области Common Properties на панели Properties появится текстовое поле свойства Content, где можно ввести простой текст:
Очевидно, что такое простое поле ввода информации нельзя использовать для определения более сложного содержимого, в том числе встраиваемой графики, анимации и т.п. Когда же требуется добавить в элемент управления сложное, составное содержимое, следует прежде всего ввести диспетчер компоновки в выбранный элемент управления графического пользовательского интерфейса. Этот диспетчер компоновки будет, в свою очередь, содержать ряд отдельных элементов, представляющих содержимое в целом.
Создание составного содержимого
Подробнее о работе с диспетчерами компоновки речь пойдет в следующих статьях, а пока найдите элемент управления типа StackPanel в библиотеке ресурсов (напомним, что интересующий вас элемент можно быстро найти, введя его имя в поле поиска Search). Дважды щелкните на нем, чтобы добавить его в главное окно приложения, представленное объектом типа Window. Затем перетащите его на элемент управления типа Button и нажмите клавишу <Alt>. В итоге объект типа StackPanel окажется в области действия элемента управления Button и будет использоваться для хранения нового составного содержимого.
При создании составного содержимого порой оказывается полезно увеличивать масштаб редактируемого элемента управления, используя доступные на монтажном столе элементы управления или колесико мыши.
В настоящий момент совершенно очевидно, что размеры встроенного диспетчера компоновки нужно увеличить, чтобы охватить им внутреннюю часть элемента управления. Это можно сделать инструментом обычного выделения Selection, доступным на панели Tools с помощью кнопки, обозначенной пиктограммой черной стрелки. В рассматриваемом здесь примере требуется расположить по горизонтали, а не по вертикали данные, хранящиеся в StackPanel. С этой целью установите в его свойстве Orientation - Horizontal.
Если вы теперь перейдете к панели Objects and Timeline, то сможете выбрать диспетчер компоновки элемента управления типа Button, т.е. объект типа StackPanel, а затем добавить любое количество дополнительных компонентов. Итак, добавьте выбранную вами геометрическую форму, например эллипс, звезду или стрелку, а также элемент управления типа Label в данный диспетчер компоновки, например:
Теперь можете выбрать каждый компонент для последующей правки. Как показано на рисунке ниже, некоторые основные свойства объекта типа Label, обозначающего метку, были изменены на панели Properties, в том числе размер шрифта в области Text, расположение текста в области Layout, а также текст ОК! самой метки в свойстве Content. Кроме того, для обводки по контуру и заполнения внутренней части формы звезды нужными цветами были специально настроены соответствующие кисти:
Но самое интересное, что для рассматриваемого здесь элемента управления была создана анимация изменения цвета звезды в течение одной секунды, при условии, что объект типа Button находится в оперативной памяти. Для этой цели было активизировано свойство AutoReverse, а в свойстве RepeatBehavior установлено значение Forever. Для того чтобы не повторять снова все особенности работы с редактором анимации, подробно рассматриваемые ранее, приведем лишь самые основные этапы создания раскадровки новой анимации:
Введите в раскадровку ключевые кадры анимации, воспользовавшись кнопкой Record Keyframe с яйцевидной пиктограммой.
Внесите изменения в свойства выбранного элемента пользовательского интерфейса, чтобы зарегистрировать изменения в его состоянии.
Обработка событий, наступающих для элементов управления с составным содержимым
При создании элемента управления с составным содержимым можно по желанию организовать обработку событий, наступающих для любых подчиненных компонентов. В частности, для компонента в форме звезды, представленного объектом типа RegularPolygon, можно обрабатывать событие MouseDown, наступающее при нажатии кнопки мыши, а для самой кнопки — событие Click. Подобным образом удается зафиксировать факт щелчка не только на кнопке вообще, но и на отдельных частях ее составного содержимого. Ниже приведен исходный код некоторых обработчиков упомянутых выше событий, при наступлении которых в главном окне приложения выводится сообщение в зависимости от того, где именно был произведен щелчок:
private void regularPolygon_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.Title = "Вы кликнули по звездочке!";
e.Handled = true;
}
private void Button_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.Title = "Вы кликнули по кнопке!";
}
В приведенном выше коде обратите внимание на следующее: при выполнении щелчка кнопкой мыши исключается распространение события по дереву разметки XAML благодаря установке логического значения true в свойстве Handled (Обработано) наступающего события, передаваемого обработчику событий в качестве аргумента. Если этого не сделать, событие от мыши будет сначала обработано на уровне формы звезды а затем на уровне самой кнопки. Но в любом случае запустите свое приложение на выполнение, нажав функциональную клавишу <F5>, чтобы проверить, будет ли кнопка реагировать на щелчки кнопкой мыши предполагаемым образом.
Повторное использование составного содержимого
Проанализировав разметку, автоматически сформированную в коде XAML, вы обнаружите, что элемент управления типа Button определен в ней предполагаемым образом. При этом диспетчер компоновки типа StackPanel определяет непосредственное содержимое данного элемента управления и сам содержит два элемента:
<Button Margin="212,141,288,0" VerticalAlignment="Top" Height="48.277"
HorizontalContentAlignment="Left" MouseDown="Button_MouseDown">
<StackPanel Orientation="Horizontal">
<ed:RegularPolygon x:Name="regularPolygon" Fill="#FFF4F4F5"
Height="32.667" InnerRadius="0.47211" PointCount="5" Stretch="Fill"
Stroke="#FFF10F0F" Width="32.667" StrokeThickness="2"
MouseDown="regularPolygon_MouseDown"/>
<Label Content="OK!" VerticalContentAlignment="Center" Padding="10,5"
FontFamily="Tekton Pro Ext" FontWeight="Bold" FontSize="18.667"
Width="70.47" HorizontalContentAlignment="Center"/>
</StackPanel>
</Button>
Но при создании анимации в среде Expression Blend IDE ее раскадровка вводится в виде именованного ресурса объекта типа Window или объекта типа UserControl. Проанализировав разметку, описывающую анимацию, вы непременно обнаружите, что объекты, содержащиеся в специальной кнопке, упоминаются в этой разметке прямо по имени, как, например, объект regularPolygon, обозначающий форму звезды в составном содержимом данной кнопки:
<Window.Resources>
<Storyboard x:Key="ColorStarAnimation" AutoReverse="True" RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)" Storyboard.TargetName="regularPolygon">
<EasingColorKeyFrame KeyTime="0" Value="#FFF10F0F"/>
<EasingColorKeyFrame KeyTime="0:0:2" Value="#FF0F27F1"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
Аналогичным образом в разметке для ооъекта типа window описывается триггер, запускающий анимационную последовательность. По существу, рассматриваемая здесь специальная кнопка действует довольно обособленно. И в связи с этим возникает следующий вопрос - что, если в пользовательском интерфейсе потребуются три специальные кнопки с формой звезды?
В настоящий момент элемент управления типа Button тесно связан с конкретны объектом типа Window, и поэтому им нельзя воспользоваться повторно. Конечно элемент управления типа Button можно скопировать и вставить для повторного использования его составного содержимого, но анимация все равно будет постоянно связана с формой звезды из оригинала кнопки.
В последующих статьях будет подробно рассмотрен процесс построения специальных объектов типа UserControl, шаблонов и стилей оформления. При этом будет показано, что чаще всего имеет смысл (и даже полезно) определять элемент управления с составным содержимым в качестве особого стиля оформления или объекта типа UserControl, поскольку именно так его можно использовать повторно.
А до тех пор просто запомните, что в большинстве элементов управления на платформах WPF и Silverlight поддерживается составное содержимое. Такое содержимое можно сформировать в среде Expression Blend IDE, введя в его пределы диспетчер компоновки и заполнив связанными элементами. С данным вопросом тесно связано понятие рассматриваемой далее модели содержимого многокомпонентных элементов управления.