Глава 3. Элементы управления и XAML
Введение
Глава 1. Модель приложения Longhorn
Глава 2. Создание приложения Longhorn
Глава 3. Элементы управления и XAML
Брент Проректор
Мудрая Сова Консалтинг
Декабрь 2003 г.
Содержимое
Элементы XAML
Панели XAML
Элементы управления
Ресурсы и стили
Графика и анимация
Службы документов
Сводка
Как вы видели в главе 2, приложения платформы Longhorn обычно состоят из объекта Application и набора страниц пользовательского интерфейса, которые вы пишете на декларативном языке разметки, называемом XAML.
Объект Application является одноэлементным и сохраняется на протяжении всего времени существования приложения. Это позволяет логике приложения обрабатывать события верхнего уровня и совместно использовать код и состояние между страницами. Объект Application также определяет, является ли приложение приложением с одним окном или приложением навигации.
Как правило, каждая страница пользовательского интерфейса записывается с использованием диалекта XML с именем XAML. Каждая страница состоит из элементов XAML, текстовых узлов и других компонентов, упорядоченных в иерархическое дерево. Иерархическая связь этих компонентов определяет, как страница отрисовывается и ведет себя.
Вы также можете считать страницу XAML описанием объектной модели. Когда среда выполнения создает страницу, она создает экземпляры всех элементов и узлов, описанных в документе XAML, и создает эквивалентную объектную модель в памяти. Вы можете управлять этой объектной моделью программным способом, например добавлять и удалять элементы и узлы, чтобы страница отображала и вела себя по-разному.
По сути, страница XAML описывает классы, которые должна создать среда выполнения, значения свойств и обработчики событий для экземпляров классов, а также иерархию объектной модели, т. е. какой экземпляр является родительским для другого экземпляра.
Все документы XAML являются XML-документами правильного формата, в которых используется определенный набор имен элементов. Поэтому все правила, касающиеся формирования правильно сформированных XML-документов, в равной степени применяются к документам XAML. Например, документ должен содержать один корневой элемент; все имена элементов чувствительны к регистру; определение элемента не может перекрывать другое определение элемента, но должно полностью содержать его и т. д. Если вы не знакомы с синтаксисом XML, сейчас настало время изучить его.
Элементы XAML
Каждая страница XAML содержит один или несколько элементов , управляющих макетом и поведением страницы. Эти элементы упорядочить иерархически в дереве. Каждый элемент имеет только один родительский элемент. Элементы обычно могут иметь любое количество дочерних элементов. Однако некоторые типы элементов, например Scrollbar, не имеют дочерних элементов; и другие типы элементов, например Border, могут иметь один дочерний элемент.
Имя каждого элемента соответствует имени управляемого класса. Добавление элемента в документ XAML приводит к тому, что среда выполнения создаст экземпляр соответствующего класса. Например, следующая разметка представляет корневой элемент DockPanel , имеющий один дочерний элемент Table . Элемент Table содержит три дочерних элемента Row . Каждый элемент Row содержит три дочерних элемента, а некоторые из них имеют дочерние текстовые узлы.
<Border xmlns="https://schemas.microsoft.com/2003/xaml"
Background="BlanchedAlmond">
<DockPanel>
<Table>
<Body>
<Row>
<Cell><Button/></Cell>
<Cell><Text>Item</Text></Cell>
<Cell><Text>Price</Text></Cell>
</Row>
<Row>
<Cell><CheckBox Checked="true"/></Cell>
<Cell><TextBox Height="50">Nissan 350Z</TextBox></Cell>
<Cell><TextBox Height="50">29.95</TextBox></Cell>
</Row>
<Row>
<Cell><CheckBox/></Cell>
<Cell><TextBox Height="50">Porsche Boxster</TextBox></Cell>
<Cell><TextBox Height="50">9.95</TextBox></Cell>
</Row>
</Body>
</Table>
</DockPanel>
</Border>
Этот документ XAML создает иерархию объектов, как показано на рисунке 3-1 и на рисунке 3-2.
Рис. 3-1. Пример объектной модели страницы XAML
Рис. 3-2. Отображение из предыдущего кода XAML (щелкните для большего изображения)
Вы можете получить доступ к большей части функциональных возможностей таких объектов, используя только разметку. Используя только разметку, можно выполнить любое из следующих действий:
- Описывать иерархический набор объектов, экземпляры которыми будет создавать среда выполнения
- Присвойте свойствам объекта значения, известные статически
- Задайте для свойств объекта значения, полученные из источника данных
- Причина сохранения измененных значений свойств в источнике данных
- Многократное изменение значения свойства с течением времени
- Привязка обработчика событий к событию объекта
Однако, хотя вы можете создать некоторые удивительные пользовательские интерфейсы, используя только разметку, вы также можете получить доступ к функциональным возможностям элемента программным способом с помощью объектной модели XAML. Объектная модель позволяет управлять всеми аспектами элементов на странице. На самом деле он предоставляет дополнительные возможности, недоступные через XAML.
Каждый элемент XAML является производным от System.Windows.UIElement или System.Windows.ContentElement, поэтому все элементы обладают рядом общих признаков. Элементы можно сгруппировать по следующим четырем основным категориям:
- Элементы управления являются производными от System.Windows.Control и обрабатывают взаимодействие с пользователем.
- Панели — это специализированные элементы управления, производные от System.Windows.Panel и обрабатывающие макет страницы и выступающие в качестве контейнеров для элементов.
- Элементы форматирования текста являются производными от System.Windows.TextElement и обрабатывают форматирование текста и структуру документа.
- Фигуры обрабатывают векторные графические фигуры.
Панели XAML
Страница XAML обычно начинается с элемента панели. Панель является контейнером для содержимого страницы и управляет расположением и отображением этого содержимого. На самом деле при отображении чего-либо с помощью XAML всегда используется панель, хотя иногда она неявная, а не описанная явным образом. Панель может содержать другие панели, что позволяет разделить поверхность дисплея на области, каждая из которых управляется ее панелью.
Существует шесть встроенных классов Panel на платформе Longhorn:
- Canvas размещает каждый дочерний элемент явным образом, используя координаты относительно области Canvas.
- DockPanel помещает свои дочерние элементы в верхнюю, нижнюю, левую, правую или центральную часть панели. При назначении нескольких дочерних элементов в одной области DockPanel размещает их горизонтально или вертикально в пределах этой области.
- FlowPanel упорядочивает свои дочерние элементы в соответствии со свойствами разбиения строк и выравнивания. Если длина содержимого превышает длину одной строки, панель будет прерывать линии, переносить строки и выравнивать содержимое соответствующим образом.
- Объект TextPanel отрисовывает несколько строк текста в нескольких текстовых форматах. Обычно он используется только в том случае, если требуется сложный макет текста. В большинстве случаев для базовой поддержки текста используется упрощенный элемент Text .
- GridPanel — это упрощенный элемент, который упорядочивает свои дочерние элементы в строках и столбцах, образующих сетку. Она полезна для создания простых таблиц, но имеет ограниченные возможности. Для сложного макета таблицы следует использовать элемент управления Таблица .
- FixedPanel размещает свои дочерние элементы на странице фиксированного макета. Элементы на страницах фиксированного макета всегда имеют одинаковое расположение и разбиение на страницы независимо от разрешения устройства или размера окна.
Как правило, эти панели обеспечивают достаточную функциональность для большинства разработчиков. Однако вы также можете создать собственные классы панели, которые позиционируют и отображают содержимое специализированным образом.
Холст
Панель Canvas обеспечивает значительную гибкость при расположении и расположении элементов на экране. Он позволяет указать расположение каждого дочернего элемента, а при перекрытии элементов можно указать порядок, в котором холст рисует перекрывающиеся элементы, изменив порядок отображения элементов в разметке.
Следующая разметка создает три перекрывающихся рисунка, как показано на рисунке 3-1: зеленый прямоугольник с оранжевой границей, полупрозрачный желтый эллипс с синей границей и некоторый текст по центру прямоугольника. (Мысль никогда больше не писать WM_PAINT обработчик для рисования таких вещей приносит слезы на моих глазах . . . . слезы радости я спешу добавить!) Платформа рисует фигуры в порядке представления, поэтому текст отображается над прямоугольником.
<Canvas xmlns="https://schemas.microsoft.com/2003/xaml" >
<Rectangle
Fill="#33CC66"
Width="2in" Height="1in"
Canvas.Top="25" Canvas.Left="50"
StrokeThickness="6px" Stroke="Orange" />
<Ellipse
Fill="yellow"
CenterX="1.5in" CenterY="1.1in"
RadiusX=".5in" RadiusY="1in"
StrokeThickness="4px" Stroke="Blue" />
<Text
Canvas.Top="50" Canvas.Left="60" Foreground="#000000"
FontWeight="Bold" FontFamily="Arial"
FontStyle="Normal" FontSize="25">Hello Shapes!</Text>
</Canvas>
Рис. 3-3. Пример использования панели Canvas
DockPanel
Панель DockPanel размещает дочерние элементы по горизонтали или вертикали относительно друг друга. Класс DockPanel проверяет свойство Dock каждого дочернего элемента, чтобы определить, как выровнять элемент по краям панели. Для свойства Dock можно задать одно из пяти значений: Top, Bottom, Left, Right или Fill.
Например, панель выравнивает первый дочерний элемент со свойством Dock , равным Top , по верхнему краю панели. Затем панель выравнивает следующий дочерний элемент со свойством Dock , равным Top под предыдущим элементом. Панель аналогичным образом выравнивает дочерние элементы со свойством Dock, равным Нижнему, Левому или Правому. Если для свойства Dock последнего дочернего элемента задано значение Fill , он займет все оставшееся пространство в DockPanel. Никогда не следует следовать элементу Dock="Fill" с другими элементами, так как последующие элементы не будут видны. Значение свойства Dock по умолчанию — Left, поэтому, если свойство Dock не задано для элемента, оно стекается горизонтально слева.
Свойство Dock является присоединенным свойством. Оно определяется классом DockPanel , но оно задается для дочернего элемента следующим образом:
<child DockPanel.Dock="Top"/>
Или в коде:
DockPanel.SetDock(child, Dock.Top)
Следующая разметка использует DockPanel и пять панелей Canvas для создания часто встречаемого пользовательского интерфейса. DockPanel выравнивает первые два холста по верхней части DockPanel. Третий холст выравнивается по нижнему краю DockPanel, четвертый — по левому краю, а пятый холст заполняет оставшееся пространство. Можно разместить меню на верхней панели, а панель инструментов — непосредственно под меню. Это решение оставляет левую панель для представления дерева, нижнюю панель для строки состояния, а оставшуюся панель для подробного представления выбранного элемента, как показано на рисунке 3-4.
<Border xmlns="https://schemas.microsoft.com/2003/xaml"
Background="White">
<DockPanel>
<Border Width="500" DockPanel.Dock="Top"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#87ceeb" >
<Text>Dock = "Top"</Text>
</Border>
<Border Width="500" DockPanel.Dock="Top"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#87ceeb" >
<Text>Dock = "Top"</Text>
</Border>
<Border Width="500" DockPanel.Dock="Bottom"
BorderThickness="2,2,2,2"
BorderBrush="Black" Background="#ffff99" >
<Text>Dock = "Bottom"</Text>
</Border>
<Border Width="200" DockPanel.Dock="Left"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#98fb98" >
<Text>Dock = "Left"</Text>
</Border>
<Border Width="300" DockPanel.Dock="Fill"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="White" >
<Text>Dock = "Fill"</Text>
</Border>
</DockPanel>
</Border>
Рис. 3-4. Пример использования панели DockPanel
FlowPanel
Панель FlowPanel предоставляет ряд функций автоматического макета и позволяет выполнять сложные представления текста и графики. Размер панели определяется с помощью ее свойств Width и Height . Затем панель отображает свои дочерние элементы таким образом, чтобы лучше всего использовать пространство панели, обтекая и выравнивая элементы по мере необходимости. Направление потока по умолчанию для FlowPanel — слева направо и сверху вниз.
В следующем примере разметки показано, как FlowPanel разрывает и заключает содержимое. FlowPanel содержит четыре квадратных холста размером в один дюйм. FlowPanel пытается отобразить дочерние элементы слева направо и сверху вниз.
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="White">
<FlowPanel>
<Border Background="Red" Width="1in" Height="1in"/>
<Border Background="Green" Width="1in" Height="1in"/>
<Border Background="Blue" Width="1in" Height="1in"/>
<Border Background="Yellow" Width="1in" Height="1in"/>
</FlowPanel>
</Border>
На рисунке 3-3 показаны выходные данные, когда FlowPanel может разместить все элементы в одной строке. На рисунке 3-4 показано, как FlowPanel упаковывает последний элемент в новую строку. На рисунке 3-5 показан наихудший случай, когда FlowPanel должен разместить каждый элемент в отдельной строке. На рисунке 3-6 показан последний элемент, перенос в новую строку, а на рис. 3-7 показан перенос каждого элемента в новую строку.
Рис. 3-5. FlowPanel разрывает линии только при необходимости.
Рис. 3-6. Панель FlowPanel с переносом последнего элемента в новую строку
Рис. 3-7. Панель FlowPanel с переносом каждого элемента в новую строку
TextPanel
Панель TextPanel форматирует, размер и рисует текст. Этот класс панели поддерживает несколько строк текста, а также несколько текстовых форматов. Класс TextPanel обычно используется, когда требуется поддержка сложного макета. Однако, если требуется только простое отображение текста, лучше использовать элемент Text .
В следующем примере разметки показано, как TextPanel разрывает и заключает содержимое в оболочку. TextPanel настраивает количество столбцов и высоту каждого столбца при изменении размера окна.
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="White">
<TextPanel
ColumnCount="3"
ColumnWidth="200px"
ColumnGap="25px"
ColumnRuleWidth="5px"
ColumnRuleBrush="blue">
<Block Background="LightGray">
<Inline FontFamily="Arial" FontWeight="Bold"
FontSize="16pt">Transcript of the
<Italic>Nicolay Draft</Italic>
of the Gettysburg Address.
</Inline>
</Block>
§
</TextPanel>
</Border>
На рисунке 3-8 показаны выходные данные.
Рис. 3-8. TextPanel с несколькими характеристиками шрифта, столбцами и форматированием
GridPanel
На панели GridPanel отображаются табличные данные. GridPanel поддерживает множество свойств, которые можно использовать для настройки макета табличных данных. Например, можно задать свойства Столбцы и Строки , чтобы управлять количеством столбцов и строк в сетке. Аналогичным образом свойства ColumnStyles и RowStyles позволяют задать коллекцию свойств, которые GridPanel применяет к строкам и столбцам соответственно.
GridPanel упорядочивает свои дочерние элементы, начиная с верхней левой ячейки и перемещаясь вправо до конца строки. Дочерний элемент может принимать несколько столбцов, если для дочернего элемента задано свойство GridPanel.ColumnSpan . Аналогичным образом GridPanel.RowSpan позволяет дочернему элементу охватывать несколько строк.
Следующая разметка отображает пользовательский интерфейс калькулятора, который выглядит примерно так же, как служебная программа Windows Calculator.
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="#DEE7F7">
<DockPanel Dock="Left">
<Border BorderThickness="0,0,0,0">
<!-- Padding="10, 10, 10, 10" -->
<GridPanel Columns="7">
<GridPanel.ColumnStyles>
<Column Width="16%"/>
<Column Width="4%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
</GridPanel.ColumnStyles>
<GridPanel.RowStyles>
<Row Height="25"/>
<Row Height="10"/>
<Row Height="35"/>
<Row Height="7"/>
<Row Height="35"/>
<Row Height="35"/>
<Row Height="35"/>
<Row Height="35"/>
</GridPanel.RowStyles>
<Border GridPanel.ColumnSpan="7" BorderBrush="#DEE7F7"
BorderThickness="2,2,2,2" Background="White">
<Text HorizontalAlignment="right"
ID="CalcText">0.</Text>
</Border>
<Text GridPanel.ColumnSpan="7"/>
<Border BorderThickness="0,0,0,0">
<GridPanel>
<Border BorderBrush="#DEE7F7" BorderThickness="2,2,2,2">
<Text Width="16%"
HorizontalAlignment="center"></Text>
</Border>
</GridPanel>
</Border>
<Text Width="4%"/>
<DockPanel GridPanel.ColumnSpan="5" Dock="Left">
<Button Width="33.33%" Foreground="Red">Backspace</Button>
<Button Width="33.33%" Foreground="Red">CE</Button>
<Button Width="33.33%" Foreground="Red">C</Button>
</DockPanel>
<Text GridPanel.ColumnSpan="7"/>
<Button Foreground="Red">MC</Button>
<Text/>
<Button Foreground="Blue">7</Button>
<Button Foreground="Blue">8</Button>
<Button Foreground="Blue">9</Button>
<Button Foreground="Red">/</Button>
<Button Foreground="Blue">sqrt</Button>
<Button Foreground="Red">MR</Button>
<Text/>
<Button Foreground="Blue">4</Button>
<Button Foreground="Blue">5</Button>
<Button Foreground="Blue">6</Button>
<Button Foreground="Red">*</Button>
<Button Foreground="Blue">%</Button>
<Button Foreground="Red">MS</Button>
<Text/>
<Button Foreground="Blue">1</Button>
<Button Foreground="Blue">2</Button>
<Button Foreground="Blue">3</Button>
<Button Foreground="Red">-</Button>
<Button Foreground="Blue">1/x</Button>
<Button Foreground="Red">M+</Button>
<Text/>
<Button Foreground="Blue">0</Button>
<Button Foreground="Blue">+/-</Button>
<Button Foreground="Blue">.</Button>
<Button Foreground="Red">+</Button>
<Button Foreground="Red">=</Button>
</GridPanel>
</Border>
</DockPanel>
</Border>
На рисунке 3-9 показаны выходные данные.
Рис. 3-9. GridPanel в качестве калькулятора
FixedPanel
Панель FixedPanel позволяет указать точное расположение и размеры каждого элемента. Элементы в FixedPanel всегда будут отображаться в одном расположении и размере на всех устройствах. Я обсудим панель FixedPanel далее в этой главе в разделе "Службы макета документов".
Элементы управления
XAML содержит все элементы управления, которые вы ожидаете от Windows: кнопки, проверка поля, переключатели, списки, поля со списком, меню, полосы прокрутки, ползунки и т. д. В этом примере показаны некоторые распространенные элементы управления, предоставляемые в Longhorn. Результаты см. на рис. 3-10.
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Header="New" />
<MenuItem Header="Open" />
</MenuItem>
<MenuItem Header="Edit">
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
</Menu>
<FlowPanel>
<Button> Button </Button>
<Border Width="15"/>
<CheckBox Checked="true"> CheckBox </CheckBox>
<Border Width="15"/>
<RadioButtonList>
<RadioButton> RadioButton 1 </RadioButton>
<RadioButton Checked="true"> RadioButton 2 </RadioButton>
<RadioButton> RadioButton 3 </RadioButton>
</RadioButtonList>
<Border Width="15"/>
<ListBox>
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
<Border Width="15"/>
<ComboBox>
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ComboBox>
<Border Width="15"/>
<DockPanel>
<VerticalSlider DockPanel.Dock="Top" Height="200"
Minimum="0" Maximum="255" Value="75"
SmallChange="1" LargeChange="16"/>
<Text DockPanel.Dock="Bottom">Slider</Text>
</DockPanel>
<Border Width="15"/>
<DockPanel>
<VerticalScrollBar DockPanel.Dock="Top"
Minimum="0" Maximum="255" Value="125" Height="200"
SmallChange="1" LargeChange="16"/>
<Text DockPanel.Dock="bottom">ScrollBar</Text>
</DockPanel>
<Border Width="15"/>
<TextBox> TextBox </TextBox>
</FlowPanel>
</DockPanel>
</Border>
Рис. 3-10. Пример элементов управления XAML
XAML также позволяет объединять элементы и элементы управления для создания расширенных эффектов. Мы называем это объединение элементов управления композицией, и это один из самых мощных аспектов Longhorn. Например, чтобы создать кнопку с изображением, поместите элемент Image внутри Button:
<Button>
<Image Source="tulip.jpg"/>
</Button>
Чтобы добавить изображение и текст в кнопку, как показано на рис. 3-11, мы используем наш старый друг DockPanel:
<Button>
<DockPanel>
<Image Source="tulip.jpg"/>
<Text DockPanel.Dock="fill" VerticalAlignment="center"> Button
<Italic>with Image!</Italic>
</Text>
</DockPanel>
</Button>
Рис. 3-11. Кнопка с изображением и текстом
Вы можете поместить практически все, что угодно, включая этот странный пример CheckBox внутри кнопки:
<Button>
<CheckBox Checked="true"> CheckBox </CheckBox>
</Button>
Композиция достаточно мощна, что многие элементы управления Longhorn фактически определяются с помощью композиции. Например, ScrollBar — это две кнопки и ползунок, а также логика обработчика событий для их объединения.
XAML также включает некоторые "примитивы", которые в основном используются с композицией элементов управления для создания более крупных эффектов. Например, ScrollViewer принимает один дочерний элемент (обычно панель) и добавляет в него полосы прокрутки. В этом примере очень большой список элементов CheckBox помещает в ScrollViewer, для которого до Longhorn требовался отдельный элемент управления, например checkedListBox Windows Forms:
<Border BorderThickness="1" BorderBrush="black">
<ScrollViewer Height="100" Width="200">
<GridPanel Columns="1">
<CheckBox Checked="true"> CheckBox 1</CheckBox>
<CheckBox Checked="true"> CheckBox 2</CheckBox>
<CheckBox Checked="true"> CheckBox 3</CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
</GridPanel>
</ScrollViewer>
</Border>
Ресурсы и стили
XAML предоставляет очень широкие возможности для настройки внешнего вида приложения с помощью сущностей, известных как стили. Тем не менее, прежде чем мы приступим к этой теме, нам нужно изучить ресурсы. Термин "ресурсы ", используемый в этом контексте, просто относится к способу повторного использования часто определенных объектов и значений. Рассмотрим пример:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<SolidColorBrush def:Name="MyColor" Color="Gold"/>
</FlowPanel.Resources>
<Button Background="{MyColor}"/>
<Ellipse Fill="{MyColor}"/>
</FlowPanel>
</Border>
Этот код определяет новый ресурс с именем MyColor, тип которого — SolidColorBrush , а значение — Gold. Этот ресурс входит в коллекцию РесурсовFlowPanel. Каждый элемент имеет коллекцию Resources . Ресурсы можно определить в любом элементе, но чаще всего они помещают только в корневой элемент , в данном случае FlowPanel.
После определения ресурса можно ссылаться на ресурс в значении свойства, поместив имя ресурса в фигурные скобки, как показано ниже:
<Button Background="{MyColor}"/>
Когда обработчик XAML видит {MyColor} в этом примере, он сначала проверка коллекцию ресурсов кнопки. Так как button не имеет определения MyColor (его коллекция Resources пуста), она будет проверка родительской кнопки — FlowPanel.
Одним из наиболее полезных видов ресурсов является стиль. Стиль — это имя класса и имя свойства, которое есть у всех элементов. Стиль определяет свойства, устанавливаемые в элементе , который затем использует указанный стиль. В этом примере определяется стильс именем MyStyle и он применяется к кнопке:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="MyStyle">
<Button Background="Red" FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button>Normal</Button>
<Button Style="{MyStyle}">Styled</Button>
</FlowPanel>
</Border>
Вы также можете определить ресурс Style без имени, который становится стилем по умолчанию для элементов, в которых явное свойство Style не указано. В этом примере к предыдущему примеру добавляется стиль по умолчанию:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style>
<Button Background="Green" FontSize="15"/>
</Style>
<Style def:Name="MyStyle">
<Button Background="Red" FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button>Normal</Button>
<Button Style="{MyStyle}">Styled</Button>
</FlowPanel>
</Border>
Вы можете выполнить наследование стилей, задав свойство BasedOn класса Style . При ссылке на новый класс Style будут заданы все свойства, которые выполнял старый стиль , а также указанные дополнительные свойства. В следующем примере определяются два стиля: первый задает свойство Background , а второй на основе первого задает свойство FontSize .
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="Style1">
<Button Background="Red"/>
</Style>
<Style def:Name="Style2" BasedOn="{Style1}">
<Button FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button Style="{Style1}">Style 1</Button>
<Button Style="{Style2}">Style 2</Button>
</FlowPanel>
</Border>
Стиль даже может задать свойства условно, используя функцию, известную как триггеры свойств. Style имеет свойство с именем VisualTriggers, которое является коллекцией PropertyTriggers. Каждый Объект PropertyTrigger задает условие с помощью свойств Property и Value и содержит коллекцию инструкций Set . Если свойство стилизованного элемента совпадает с этим значением, применяются инструкции Set , а если условие больше не соответствует действительности, значения не применяются, как если бы они никогда не были заданы в первую очередь. В этом примере используются триггеры свойств, чтобы сделать кнопку зеленой при наведении указателя мыши на кнопку, а в противном случае — красным:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="Style1">
<Button Background="Red"/>
<Style.VisualTriggers>
<PropertyTrigger Property="IsMouseOver" Value="true">
<Set PropertyPath="Background" Value="Green"/>
</PropertyTrigger>
</Style.VisualTriggers>
</Style>
</FlowPanel.Resources>
<Button Style="{Style1}">Style 1</Button>
</FlowPanel>
</Border>
Многие элементы управления XAML используют композицию элементов управления. Они объединяют несколько небольших элементов управления для создания более крупного и сложного элемента управления. Стили даже позволяют вам изменить это! Указав другую композицию, можно полностью переопределить внешний вид элемента управления, сохраняя при этом его поведение.
После объявления элемента style и его свойств <тег Style.VisualTree> указывает внутри элемента Style , какие элементы следует создать для создания более крупного элемента управления. Свойства дочерних элементов можно задать обычным образом и предоставить этим дочерним элементам собственные. Для задания значений свойств также можно использовать псевдонимы свойств. Например, Name1="*Alias(Target=Name2)" присвоит свойству Name1 дочернего элемента управления свойство Name2 большего размера. В следующем примере создается стиль для button , который изменяет композицию для получения круглого вида, как показано на рисунке 3-12. Свойства фона и содержимого кнопки псевдонимируются в соответствующих точках визуального дерева.
<Border Background="white"
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition">
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="RoundButton">
<Button FontSize="20"/>
<Style.VisualTree>
<Canvas>
<Rectangle ID="MainRect"
RadiusX="10" RadiusY="10"
Fill="*Alias(Target=Background)"
Width="100%" Height="100%" />
<FlowPanel Width="100%" Height="100%" >
<ContentPresenter
ContentControl.Content="*Alias(Target = Content)"
Margin="15,3,15,5"/>
</FlowPanel>
</Canvas>
</Style.VisualTree>
</Style>
</FlowPanel.Resources>
<Button Style="{RoundButton}">
standard RoundButton
</Button>
<Button Background="red" Style="{RoundButton}">
red RoundButton
</Button>
<Button>
standard button
</Button>
<Button Background="red">
red standard button
</Button>
</FlowPanel>
</Border>
Рис. 3-12. Несколько кнопок RoundButton и стандартных кнопок в FlowPanel
Графика и анимация
XAML обеспечивает обширную поддержку рисования фигур, преобразования состояния объекта и анимации почти любого свойства объекта. Элементы Shape используются для рисования, Элементы Transform для изменения свойства или объекта и Элементы Анимации для изменения свойства объекта с течением времени.
Фигуры
XAML предоставляет набор элементов фигуры для рисования, включая эллипс, линию, прямоугольник, путь, многоугольник и ломаную линию. Фигура имеет заливку, которая является цветом фона, и stroke, который является цветом контура. Заливка и обводка по умолчанию — прозрачные, поэтому убедитесь, что задан хотя бы один из них. Свойство StrokeWidth управляет толщиной контура.
Фигуры не могут иметь дочерние элементы. Обычно фигуры размещаются внутри холста, поэтому первая фигура в разметке будет первой нарисованной. В этом примере показаны некоторые основные фигуры, которые также можно увидеть на рис. 3-13:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<Ellipse CenterX="70" CenterY="75"
RadiusX="30" RadiusY="50"
Fill="yellow" Stroke="red" StrokeThickness="15"/>
<Rectangle RectangleLeft="150" RectangleTop="20"
RectangleHeight="100" RectangleWidth="40"
Fill="lightBlue" Stroke="green"/>
<Line X1="20" Y1="220" X2="150" Y2="240"
Stroke="black" StrokeThickness="5"/>
<Polygon Points="220,140 270,240 170,240"
StrokeLineJoin="Round"
Stroke="black" StrokeThickness="20"/>
</Canvas>
</Border>
Рис. 3-13. Различные фигуры на холсте
До сих пор мы использовали только сплошные цвета со свойствами Stroke и Fill . Но в XAML почти везде, где можно использовать цвет, можно указать Кисть. SolidColorBrush — это тип кисти, которую мы использовали до сих пор, но XAML также поддерживает ImageBrush, LinearGradientBrush и RadialGradientBrush. ImageBrush имеет свойство ImageSource , указывающее имя файла изображения. SolidColorBrush имеет свойство Color . LinearGradientBrush и RadialGradientBrush содержат GradientStopCollection, что позволяет выполнять очень сложные градиенты. В этом примере четыре кисти определяются как ресурсы и используются в качестве многоточия Stroke и Fill . Как они выглядят на рис. 3-14.
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Border.Resources>
<LinearGradientBrush def:Name="lineargradient" StartPoint="0,0"
EndPoint="1,1" >
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="white" Offset="1"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<RadialGradientBrush def:Name="radialgradient" Focus="0.3,0.3">
<RadialGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="red" Offset="0"/>
<GradientStop Color="yellow" Offset="1"/>
</GradientStopCollection>
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
<ImageBrush def:Name="image" ImageSource="Tulip.jpg" TileMode="Tile"/>
<SolidColorBrush def:Name="solid" Color="gray"/>
</Border.Resources>
<Canvas Height="400" Width="400">
<Ellipse CenterX="100" CenterY="75"
RadiusX="90" RadiusY="50"
Fill="{lineargradient}" Stroke="{image}" StrokeThickness="15"/>
<Ellipse CenterX="300" CenterY="170"
RadiusX="50" RadiusY="150"
Fill="{radialgradient}" Stroke="{solid}" StrokeThickness="15"/>
</Canvas>
</Border>
Рис. 3-14. Градиенты на работе
Преобразования
XAML поддерживает несколько типов преобразований. RotateTransform поворачивается на величину свойства Angle . TranslateTransform перемещает объекты в соответствии со свойствами X и Y . ScaleTransform сжимается или растягивается в соответствии со свойствами ScaleX и ScaleY . С помощью свойств AngleX, AngleY и Centerвыполняется неравномерное распределение. MatrixTransform поддерживает произвольные аффинные преобразования. Наконец, TransformCollection является преобразованием, которое позволяет объединять несколько преобразований вместе.
Некоторые классы, например Brush, имеют свойство Transform . В других случаях можно использовать элемент TransformDecorator , имеющий свойство Transform . TransformDecorator преобразует свой дочерний элемент. (Как и Border, у него может быть только один дочерний элемент.) TransformDecorator может содержать любые дочерние элементы, включая фигуры, панели и элементы управления. В этом примере используется для TransformDecorators. Первый содержит эллипс и поворачивает его на 45 градусов. Второй TransformDecorator содержит элемент ListBox и одновременно поворачивает и масштабирует ListBox. Вы можете увидеть, как выглядят фигуры на рис. 3-15.
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<TransformDecorator Transform="rotate 45">
<Ellipse CenterX="100" CenterY="75"
RadiusX="90" RadiusY="50"
Fill="white" Stroke="black" StrokeThickness="15"/>
</TransformDecorator>
<TransformDecorator Canvas.Top="200" Canvas.Left="100">
<TransformDecorator.Transform>
<TransformCollection>
<RotateTransform Angle="135"/>
<ScaleTransform ScaleX="2" ScaleY="4"/>
</TransformCollection>
</TransformDecorator.Transform>
<ListBox >
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
</TransformDecorator>
</Canvas>
</Border>
Рис. 3-15. Неравномерное распределение listBox и Ellipse
Анимации
XAML также поддерживает анимации. Вы можете анимировать почти каждое свойство. Некоторые свойства имеют соответствующее свойство Animations, например RotateTransform.Angle и RotateTransform.AngleAnimations. В других случаях можно назначить коллекцию анимации свойству с помощью синтаксиса составных свойств. Например, см. следующий код:
<Button>
<Button.Width>
… put animation collection here …
</Button.Width>
</Button>
Каждый тип свойства имеет отдельную коллекцию анимаций. Тип Button.Width — Length, поэтому используется LengthAnimationCollection. Аналогичным образом, сами объекты анимации зависят от типа анимируемого свойства — LengthAnimationCollection содержит набор объектов LengthAnimation .
Объекты анимации имеют свойства From и To , типы которых соответствуют типу анимируемого свойства. Объект анимации также имеет свойства Begin, Duration и End , которые измеряются в секундах и управляют временем анимации. Begin также поддерживает значение Immediate, а Duration — неопределенный. Для автоматического повторения анимации можно использовать свойства RepeatCount и RepeatDuration . Свойство Fill указывает, что происходит со свойством после завершения анимации. Fill="Hold" является одним из самых важных значений; свойство сохраняется в значении анимации End .
Классы анимации не являются частью пространства имен XAML по умолчанию, поэтому необходимо использовать <? Конструкции сопоставления> и xmlns для загрузки пространства имен MSAvalon.Windows.Media.Animation . Так как это пространство имен содержит классы из нескольких библиотек DLL, вам потребуется отдельный <? Сопоставление> и xmlns для каждой библиотеки DLL.
В следующем примере анимируются два свойства: RotateTransform.Angle и Button.Width , которые используют классы из обоих пространств имен анимации. На рисунке 3-16 показана кнопка в разное время.
<?Mapping XmlNamespace="animC" ClrNamespace="MSAvalon.Windows.Media.Animation"
Assembly="PresentationCore" ?>
<?Mapping XmlNamespace="animF" ClrNamespace="MSAvalon.Windows.Media.Animation"
Assembly="PresentationFramework" ?>
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:animC="animC"
xmlns:animF="animF"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<TransformDecorator Canvas.Top="200" Canvas.Left="100">
<TransformDecorator.Transform>
<TransformCollection>
<RotateTransform Angle="135">
<RotateTransform.AngleAnimations>
<animC:DoubleAnimationCollection>
<animC:DoubleAnimation From="0" To="360" Duration="4"
AutoReverse="True"
RepeatDuration="Indefinite"/>
</animC:DoubleAnimationCollection>
</RotateTransform.AngleAnimations>
</RotateTransform>
</TransformCollection>
</TransformDecorator.Transform>
<ListBox >
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
</TransformDecorator>
<Button Width="40" Canvas.Top="10" Canvas.Left="10">
<Button.Width>
<animF:LengthAnimationCollection>
<animF:LengthAnimation From="40" To="300"
AutoReverse="true" Begin="1" Duration="1.2"
RepeatDuration="Indefinite"/>
</animF:LengthAnimationCollection>
</Button.Width>
Button
</Button>
</Canvas>
</Border>
Рис. 3-16. Представления анимированной кнопки в разное время
Службы документов
Платформа Longhorn предоставляет широкие возможности, поддерживающие более удобный просмотр документов в Интернете. Существует две main службы: элемент управления, предназначенный для просмотра, разбиения на страницы и навигации по содержимому документа, и службы макета, предназначенные для улучшения возможностей чтения.
Элемент управления PageViewer
Элемент управления PageViewer используется для отображения документа пользователю для просмотра в Интернете. Элемент управления PageViewer предоставляет функции разбиения на страницы и навигации по страницам. Элемент управления автоматически форматирует содержимое документа на отдельные страницы. Пользователь может напрямую переходить на разные страницы с помощью элементов управления, предоставляемых средством просмотра страниц.
Разбиение на страницы и навигация
Традиционно веб-содержимое, например веб-страницы, было непрерывным. Пользовательский интерфейс предоставляет полосы прокрутки, позволяющие просматривать содержимое, которое не может поместиться в видимой области. По сути, вы "прокрутите" окно представления до позиции в документе, который вы хотите увидеть.
С помощью разбиения на страницы содержимое документа можно разделить на одну или несколько отдельных страниц, как в книге. Платформа Longhorn обеспечивает поддержку содержимого с разбивкой на страницы, включив несколько элементов управления, которые помогают отображать содержимое, отображаемое в виде дискретных страниц, и перемещаться по ним. Кроме того, Longhorn предоставляет программный интерфейс приложения для разбиения на страницы (API) для расширения этих возможностей и полнофункциональной поддержки разбиения на страницы для пользовательских приложений разбиения на страницы.
Элемент управления PageViewer на самом деле представляет собой сложный элемент управления, созданный из небольших элементов управления с использованием методов композиции элементов управления, описанных ранее. Элемент управления PageViewer использует элементы управления PageSource и PageElement для предоставления функций разбиения на страницы. Элемент управления PageSource разрывает и форматирует содержимое на разных страницах. Элемент управления PageElement отрисовывает одну страницу. Элемент управления PageViewer также использует элемент управления PageBar для навигации по страницам.
Использовать элемент управления PageViewer очень просто. Чтобы отобразить известный документ, его можно использовать, как показано в следующем коде. Конечно, можно подключить обработчики событий и изменить исходный документ, чтобы средство просмотра страниц отображал различные документы.
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<PageViewer Source="AuthorsandPublishers.xaml" />
</Border>
На рисунке 3-17 показано средство просмотра страницы, размещенное в окне браузера с документом. Обратите внимание на элементы управления навигацией по страницам в верхней части документа.
Рис. 3-17. Элемент управления PageViewer
Службы макетов документов
Longhorn также предоставляет службы макета документов, предназначенные для улучшения работы с чтением. Longhorn содержит поддержку двух новых типов документов:
- Документы адаптивного потока
- Документы макета исправлены
Эти новые форматы документов позволяют разработчикам предоставлять пользователям приложений более удобные возможности для чтения документов.
В документах адаптивного потока используются специализированные элементы разметки, которые объявляют, что документ должен быть адаптивный. Longhorn автоматически оптимизирует адаптивный документ для оптимального использования доступного пространства экрана и обеспечивает максимальное удобство чтения для пользователя в зависимости от возможностей или ограничений его системы.
Например, у пользователя может быть один из недавно представленных широкоэкранных дисплеев с пропорциями 16 на 9. Очень трудно прочитать строку текста, которая охватывает длинную горизонтальную линию. В зависимости от ширины окна адаптивный документ может разделить текст на два, три или более столбцов, что сокращает количество усилий пользователя при сканировании текстовой строки.
В другом примере документ может содержать изображение и текст, которые обтекают изображение. При уменьшении размера окна документа в неадаптивном документе изображение остается фиксированным, и вы увидите все меньше и меньше текста. Адаптивный документ может сжать изображение, если он определяет, что в окне отображается недостаточно текста. Это позволяет читателю по-прежнему получить общее представление о том, что изображено на изображении, но продолжать читать текст в контексте изображения. В меньшем окне просмотр каждого пикселя изображения, скорее всего, будет менее важным и полезным для читателя, чем возможность прочитать больше текста. Альтернативный вариант, например разделение изображения и окружающего текста на отдельные страницы, не позволяет автору документа представить текст и изображение вместе в контексте.
Документы фиксированного макета отображаются одинаково каждый раз, независимо от размера экрана, окна или выходного устройства. Документ фиксированного макета создается с помощью специализированных элементов разметки или путем печати документа с помощью драйвера принтера Microsoft Windows Vector Graphics (WVG).
Документы адаптивного макета
В документе адаптивного макета вы предоставляете ключевые параметры в разметке корневого уровня. Затем Longhorn может отображать документ таким образом, чтобы наилучшим образом использовать область окна и повысить его удобочитаемость. Longhorn автоматически определяет оптимальную ширину и количество столбцов для страницы, идеальные размеры для всех текстовых элементов, оптимальные размеры и позиции для всех фигур, а также ширину полей и желобов, чтобы обеспечить наилучшее общее представление содержимого.
Создание документа адаптивного макета
Чтобы создать документ адаптивного макета, используйте декларативную разметку следующего вида:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<AdaptiveMetricsContext ColumnPreference="Medium"
FontFamily="Arial">
<TextPanel Background="white">
<Section>
<Heading OutlineLevel="1">Adaptive Layout Example</Heading>
<Paragraph>
This example shows the advanced capabilities of Adaptive Flow
Layout. Lorem ipsum dolor sit amet, consectetuer adipiscing
elit, sed diam nonummy nibh euismod tin cidunt ut laoreet dolore
magna aliquam erat volutpat. Ut wisi enim ad minim veni am, quis
nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip
ex ea commodo consequat. Duis autem vel eum iriure.</Paragraph>
<Paragraph>
<Image TextPanel.FlowBehavior="Figure" Source="picture1.jpg"
TextPanel.Emphasis="Medium" />
Notice how images and text are flowed intelligently to enhance the
reading experi ence. Lorem ipsum dolor sit amet, consectetuer
adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat. Ut wisi e nim ad minim veniam,
quis nostrud exerci tation ullamcorper suscipit lobortis ni sl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure.
</Paragraph>
<Paragraph>Adaptive layout is an exciting new feature of Longhorn.
<Image TextPanel.FlowBehavior="Figure" Source="picture2.jpg"
TextPanel.Emphasis="Low" />
Lorem ipsum dolor sit amet, consectetuer
adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat. Ut wisi e nim ad minim veniam,
quis nostrud exerci tation ullamcorper suscipit lobortis ni sl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure.
</Paragraph>
</Section>
</TextPanel>
</AdaptiveMetricsContext>
</Border>
Документы Fixed-Layout
Документ с фиксированным макетом используется для представления содержимого документа в том же макете и формате, независимо от используемого программного обеспечения, оборудования и операционной системы приложения. Кроме того, документ с фиксированным макетом отображается одинаково на всех устройствах вывода. Документ с фиксированным макетом — это набор объектов, которые совместно описывают внешний вид одной или нескольких страниц.
Создание документа Fixed-Layout
Для создания документа с фиксированным макетом можно использовать два разных метода:
- Печать документа без разметки в файл с помощью драйвера принтера Longhorn
- Написание документа с фиксированным макетом с помощью XAML
При печати документа с помощью большинства приложений Microsoft Win32 (например, Microsoft Office) с помощью драйвера принтера Longhorn драйвер принтера создаст XAML-файл, содержащий разметку для разбивки на страницы и размещения каждого символа, изображения или векторного рисунка в печатном документе.
Вы можете вывести документ в виде файла разметки напрямую или включить файл разметки в контейнер. При выборе выходных данных контейнера можно также применить к документу цифровые права и защиту документов.
Кроме того, можно создать XAML с помощью редактора. Ниже приведен пример скелетного документа с фиксированным макетом.
<FixedPanel xmlns="https://schemas.microsoft.com/2003/xaml/" >
<FixedPage Width="8.50in" Height="11.00in"> <!-- PAGE 1 -->
<Text FontFamily="Arial" FontSize="8.4" FixedPage.Left="1.250in"
FixedPage.Top="0.530in" FontWeight="Bold">1.</Text>
<Text FontFamily="Arial" FixedPage.Left="1.350in" FixedPage.Top="0.500in"
FontWeight="Bold" FontSize="12">Fixed Document</Text>
</FixedPage>
<FixedPage>
<Text>This is page 2</Text>
</FixedPage>
<FixedPage>
<Text>This is page 3</Text>
</FixedPage>
</FixedPanel>
Сводка
Панели позволяют разделить поверхность дисплея на области с разными характеристиками макета. У вас есть множество элементов управления, которые можно использовать для заполнения панелей дисплея. Фигуры, преобразования и анимации позволяют создавать динамические графические выходные данные. С помощью композиции элементов управления можно объединить эти функции для создания практически любого пользовательского интерфейса. Вы можете создавать адаптивные документы, которые интеллектуально выкладывают содержимое и упрощают чтение. Кроме того, можно точно расположить каждый элемент на странице и явно управлять разбиением на страницы, чтобы создать документ, который отображается точно так, как вы хотите, независимо от устройства вывода. Более того, все это можно сделать декларативно с помощью XAML. Это уверено, как черт бьет написание WM_PAINT обработчика сообщений!