Разработка информационных систем для Windows Store

Реализация пользовательского интерфейса. Элементы управления. Стили. Ресурсы

Разбить на страницы
Показывать лекцию целиком

Для реализации элементов интерфейса в Winodws 8 используются базовые элементы управления. В среде разработки Visual Studio имеется стандартный набор элементов управления, которые являются неотъемлемой частью любого интерфейса.

Класс Control

Класс является базовым для всех элементов управления, наделяя их базовыми свойствами Windows.UI.Xaml.Controls.Control. Начнем с трех свойств, которые определяют цветовые характеристики элементов управления:

  • Background - тут содержатся свойства фона, который, как правило, является поверхностью элемента управления;
  • Foreground - это свойство задает цвет текста, который может присутствовать в качестве содержимого элементов управления;
  • Opacity - это свойство (наследуется от UIElement) определяет прозрачность элемента управления. Прозрачность задается в процентах и варьируется от 0 до 1.
  • Свойства Background и Foreground могут принимать объект типа Brush, описывающий кисть. В главе, посвященной работе с графикой, мы рассмотрим доступные кисти, а сейчас представляем пример работы с самой простой кистью - SolidBrush:

    <StackPanel>
    <Button Background="#FFFF0000" Foreground="#FF00FF00"
    Content="Hello"></Button>
    <Button Background="Red" Foreground="LightGreen"
    Content="Hello"></Button>
    <Button Content="Hello">
    <Button.Background>
    <SolidColorBrush Color="Red"></SolidColorBrush>
    </Button.Background>
    <Button.Foreground>
    <SolidColorBrush Color="LightGreen"></SolidColorBrush>
    </Button.Foreground>
    </Button>
    </StackPanel> 

    В этом примере цвет задается сразу тремя способами: в шестнадцатеричном представлении, с использованием возможности конвертера значений свойств в XAML, явным созданием объекта SolidColorBrush. Аналогично свойства можно устанавливать и из C# кода:

    btn.Background = new SolidColorBrush(Colors.Red); 

    Тут Colors представляет собой специальный класс, определяющий несколько популярных цветов.

    Если используемый элемент работает с текстом, то для установки шрифта текста могут пригодиться следующие свойства:

  • FontFamily - задает имя шрифта, который Вы хотите использовать;
  • FontSize - размер шрифта в единицах Silverlight;
  • FontStyle - позволяет задать стиль шрифта, такой как Normal или Italic;
  • FontWeight - задает вес текста, например Bold;
  • FontStretch - используется для поддержки шрифтов OpenType, в частности позволяет сжимать или растягивать текст.
  • Ниже приведен пример использования перечисленных свойств, применяемых для установки надписи кнопки:

    <Button Background="Red" 
      Foreground="LightGreen" Content="Hello"
    FontFamily="Arial"
    FontSize="16"
    FontStyle="Italic"
    FontWeight="Bold">
    </Button> 

    Следующие несколько свойств позволяют задать размеры элемента, а также отступы от соседних элементов и от содержимого:

  • Width - длина элемента управления;
  • Height - ширина элемента управления;
  • Padding - расстояние от содержимого до границ элемента;
  • Margin - расстояние от каждой из границ до границ соседних элементов.
  • Кнопки

    В WinRT представлено большое количество кнопок. Среди них и новые типы, такие как ToggleSwitch. Вот краткое описание существующих кнопок:

  • Button - классическая кнопка, содержащая в качестве контента любой объект типа UIElement и инициирующая событие Click;
  • ToggleButton - тип кнопки, используемый для имитации эффекта залипания. Кнопка может быть в двух состояниях: нажатой и отпущенной. Чтобы обрабатывать изменение состояния кнопки, используется событие Checked;
  • RepeatButton - в отличие от классической кнопки, этот вид кнопки позволяет непрерывно генерировать событие Click, если кнопка остается нажатой, то есть удерживается пользователем в этом состоянии;
  • CheckBox - эта кнопка является прямым наследником ToggleButton и реализует простейший флажок. В отличие от ToggleButton, флажок можно устанавливать в промежуточное состояние, но только из кода и только если свойство IsThreeState установлено как true;
  • RadioButton - этот элемент управления полностью аналогичен CheckBox, но предоставляет возможность размещать целый набор элементов в группы, позволяя сделать единственный выбор;
  • HyperlinkButton - подобный тип кнопки чаще всего используется внутри текста для организации переходов на другие страницы. Кнопка по умолчанию выглядит как обычная гиперссылка в браузере;
  • ToggleSwitch - этот тип кнопки крайне интересен в условиях появления Touch-интерфейсов, так как с его помощью можно легко выполнять переключения состояния. Элемент очень напоминает CheckBox, но имеет совершенно уникальное представление.
  • Поскольку ToggleSwitch является новым элементом управления, хотелось бы продемонстрировать пример его работы. Код ниже задает такой элемент и позволяет выполнять переключение между двумя состояниями "Да" и "Нет":

     <ToggleSwitch OffContent="Нет" OnContent="Да"></ToggleSwitch> 

    Вот что мы увидим на экране:

    (рис 7.1)

    Этот элемент пришел с платформы Windows Phone и полностью оптимизирован для работы с помощью пальцев.

    Следующий пример, демонстрирующий создание группы элементов RadioButton:

    <StackPanel>
    <RadioButton Content="Choice 1" IsChecked="True"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    </StackPanel> 

    В результате работы кода мы увидим следующую картину:

    (рис 7.2)

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

    <Button MaxHeight="150" MaxWidth="200">
    <Button.Content>
    <MediaElement Source="Wildlife.wmv"></MediaElement>
    </Button.Content>
    </Button> 

    Текстовые элементы управления

    В Windows Runtime выделяют три типа базовых элементов управления, позволяющих редактировать текст:

  • TextBox - позволяет вводить простой текст в виде одной или нескольких строк;
  • PasswordBox - текст скрывается с помощью специальных символов;
  • RichEditBox - позволяет вводить форматированный текст. Если рассматривать свойства таких элементов, как TextBox и PasswordBox, можно выделить:
  • AcceptsReturn - позволяет выполнять перевод каретки при вводе текста;
  • IsReadOnly - определяет, будет ли текстовое поле доступно для ввода;
  • SelectedText - возвращает выделенный текст;
  • SelectionLength - позволяет получить или задать размер текущего выделения;
  • SelectionStart - позволяет получить или задать позицию символа, с которого нужно произвести выделение;
  • SelectionBackground - определяет цвет фона выделенного текста;
  • SelectionForeground - задает цвет шрифта выделенного текста;
  • TextWraping - определяет, будет ли текст переходить на другую строку, если он не помещается в видимой части одной строки.
  • <TextBox AcceptsReturn="True" TextWrapping="Wrap"
       Width="300" Height="200">
         </TextBox> 

    Элементу TextBox можно противопоставить элемент управления TextBlock, задачей которого является отображение текста. Оба эти элемента способны удовлетворить все нужды разработчика в редактировании и отображении простого текста.

    Если же говорить о форматированном тексте, тут требуется применять RichTextEdit и RichTextBlock. Если первый элемент позволяет ввести и редактировать форматированный текст, то второй - отображает только чтение. Оба элемента являются контейнерами для других элементов. Так, основным наполнением этих элементов выступает набор элементов Paragraph, которые описывают параграфы текстового документа. В свою очередь, параграф может включать набор из следующих элементов:

  • Run - задает обычный текст;
  • Span - служит для группировки других элементов;
  • Bold - определяет жирное начертание символов;
  • LineBreak -задает переход на другую строку;
  • Italic - определяет рукописное начертание символов;
  • Underline - выделяет текст подчеркиванием;
  • HyperLink - создает гиперссылку, которая становится активной только в режиме ReadOnly элемента RichTextArea;
  • InlineUIContainer - позволяет вставить в документ любой из элементов, порожденных UIElement.
  • Ниже пример элемента RichTextBlock, отображающего текст с минимальным форматированием:

    <RichTextBlock HorizontalAlignment="Left"
    Name="rArea" VerticalAlignment="Top"
    Height="300" Width="400" >
    <Paragraph>
    <Bold>This is a bold text</Bold>
    <LineBreak></LineBreak>
    <Underline>This is an underline text</Underline>
    <LineBreak></LineBreak>
    <Italic>This is an italic text</Italic>
    <LineBreak></LineBreak>
    This is a button:
    <InlineUIContainer>
    <Button Content="Button"></Button>
    </InlineUIContainer>
    </Paragraph>
    </RichTextBlock> 

    В результате на экране отобразится следующий контент:

    (рис 7.3)

    Естественно, создавать и заполнять RichTextBlock можно и с помощью кода на C. Вот небольшой пример кода:

    Bold b = new Bold();
    b.Inlines.Add("This is a bold text");
    Italic i = new Italic();
    i.Inlines.Add("This is an italic text");
    Underline u = new Underline();
    u.Inlines.Add("This is an underlined text");
    Paragraph myPar = new Paragraph();
    myPar.Inlines.Add(b);
    myPar.Inlines.Add(new LineBreak());
    myPar.Inlines.Add(i);
    myPar.Inlines.Add(new LineBreak());
    myPar.Inlines.Add(u);
    rArea.Blocks.Add(myPar); 

    Понятие стиля

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

    Рассмотрим небольшой пример, демонстрирующий создание четырех кнопок.

    <StackPanel>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 1" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 2" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 3" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 4" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    </StackPanel> 

    Таким образом, создав всего четыре кнопки, продублировали множество строк кода. Это не только значительно увеличивает размер файла, но и ведет к возникновению ошибок. Ведь указав неверно один атрибут, можно испортить внешний вид всего интерфейса.

    Для выделения общих свойств в отдельный стиль в XAML используется специальный элемент Style. Поскольку он не должен входить в дерево элементов, а лишь задает набор свойств группы элементов, то располагать его следует внутри ресурсов приложения, страницы или отдельного элемента (в зависимости от области применения).

    Продемонстрируем работу элемента Style на примере. Для этого определим следующий блок кода сразу после открывающего элемента:

    Page.
    <Page.Resources>
    <Style x:Key="buttonStyle" TargetType="Button">
    <Setter Property="Background" Value="Green"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="FontFamily" Value="Arial"></Setter>
    <Setter Property="FontSize" Value="12"></Setter>
    <Setter Property="FontWeight" Value="Bold"></Setter>
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="BorderThickness" Value="3"></Setter>
    </Style>
    </Page.Resources> 

    Как видите, чтобы задать стиль, необходимо указать ключ и тип элементов, для которых будет применяться стиль. Ключ используется для поиска необходимого стиля, а TargetType определяет, к каким элементам применим стиль. Далее с помощью набора элементов Setter мы перечислили все свойства и их значения. Код XAML интерфейса выглядит следующим образом.

    <StackPanel>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 1">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 2">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 3">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 4">
    </Button>
    </StackPanel> 

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

    <Page.Resources>
    <Style TargetType="Button">
    <Setter Property="Background" Value="Green"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="FontFamily" Value="Arial"></Setter>
    <Setter Property="FontSize" Value="12"></Setter>
    <Setter Property="FontWeight" Value="Bold"></Setter>
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="BorderThickness" Value="3"></Setter>
    </Style>
    </Page.Resources>
    <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
    <StackPanel>
    <Button Width="100" Height="50"
    Content="Button 1">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 2">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 3">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 4">
    </Button>
    </StackPanel>
    </Grid> 

    Стили представляют собой очень мощный механизм, позволяющий сделать не только Ваше приложение в едином формате, но и придать общность большинству запускаемых приложений. Чтобы у разработчика была возможность создавать страницы, придерживаясь единого стиля, Visual Studio включает в любой проект файл StandardStyles.xaml, который определяет набор стандартных стилей на все случаи жизни. Так, попробуйте модифицировать код выше, прописав кнопкам стиль BackButtonStyle.

    <StackPanel>
    <Button Width="100" Height="50"
    Content="Button 1" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 2" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 3" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 4" Style="{StaticResource BackButtonStyle}">
    </Button>
    </StackPanel> 

    В результате работы кода на экране появится следующая картина. Как видно из рисунка, цвет одной из кнопок немного отличается. Дело в том, что стиль определяет не только внешний вид кнопки, но и ее поведение при наведении мышью, выборе и т. д. Все это возможно благодаря специальным свойствам, позволяющим задавать шаблоны элементов управления.

    BasedOn-стили

    XAML в Windows Runtime поддерживает и BasedOn-стили. Это позволяет задать общие стили применительно к базовым классам для общей группы элементов управления (или для конкретного типа элементов управления) и определить дополнительные стили путем наследования. Ниже приведен пример BasedOn-стиля.

    <Style x:Key="baseStyle" TargetType="Button" >
    <Setter Property="Width" Value="100"></Setter>
    </Style>
    <Style x:Key="btnStyleRus"
    BasedOn="{StaticResource baseStyle}" TargetType="Button">
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="Content" Value="Кнопка"></Setter>
    </Style>
    <Style x:Key="btnStyle"
    BasedOn="{StaticResource baseStyle}" TargetType="Button">
    <Setter Property="Foreground" Value="Green"></Setter>
    <Setter Property="Content" Value="Button"></Setter>
    </Style> 

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

    Ресурсы

    Выше говорилось о возможности создания стилей. Которые, как было отмечено, не должны входить в дерево XAML-элементов. Все стили записывали внутри свойства Resources, принадлежащего объекту Page. Подобное свойство есть у всех объектов XAML, порожденных от FrameworkElement, а также у объекта приложения (Application). Благодаря ресурсам разработчик может сохранять стили и другие части XAML-кода до востребования. Так, в ресурсы можно выделять объекты некоторых типов, стили, шаблоны данных и др. Фактически, свойство Resources ссылается на некий словарь, который может быть доступен как из кода, так и из XAML.

    Если используются ресурсы на уровне приложения, то доступ к ресурсу может быть осуществлён лишь по ключу, вне зависимости от того, в каком из родительских элементов объявлен ресурс. Если же ресурс был объявлен в одном из дочерних элементов, то он не может использоваться родительскими элементами.

    Рассмотрим небольшой пример.

    <Page.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </Page.Resources>
    <StackPanel>
    <Button Width="100" Height="50"
    Background="{StaticResource myBrush}"
    Content="Button 1" Margin="5">
    </Button>
    </StackPanel>

    Здесь определили в роли ресурса градиентную кисть, указав в качестве ключа (он же является именем) myBrush. Данный ключ будет использоваться для доступа к ресурсу. Как Вы могли заметить, доступ к ресурсу определяется с помощью расширения разметки StaticResource. Достаточно указать имя ключа в качестве параметра.

    В примере выше разместили ресурсы внутрь элемента Page, который является контейнером для интерфейса. Это обеспечивает видимость ресурсов для любого дочернего элемента. Если мы хотим ограничить область видимости, то ресурсы можно разместить в любом из дочерних элементов, например в StackPanel.

    <StackPanel>
    <StackPanel.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </StackPanel.Resources>
    <Button Width="100" Height="50"
    Background="{StaticResource myBrush}"
    Content="Button 1" Margin="5">
    </Button>
    </StackPanel> 

    Таким образом, для конечного элемента управления нет никакой разницы, где находятся ресурсы. Главное, чтобы они были в области видимости элемента, а доступ к ним осуществляется по одинаковой схеме.

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

    <Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application4">
    <Application.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </Application.Resources>
    </Application> 

    Выделение ресурсов объектов в отдельные файлы

    Ресурсы можно хранить в отдельных файлах и собирать в нужном месте с помощью элемента ResourceDictionary. Вынесем кисть из предыдущего примера в отдельный файл RD1.xaml.

    <ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </ResourceDictionary> 

    Для подключения внешнего файла к интерфейсу приложения используется все тот же ResourceDictionary.

    <Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application4">
    <Application.Resources>
    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="RD1.xaml" />
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    </Application.Resources>
    </Application> 

    Если у вас несколько файлов - не проблема. Перечислите их все. Обратите внимание, что стандартный файл StandardStyles.xaml как раз и оформлен как внешний файл ресурсов, который подключается внутри файла App.xaml.

    Если Вы хотите подключить файл с ресурсами в ресурсы одного из элементов, то это делается аналогичным образом.

    Краткие итоги

    Рассмотрен процесс создания пользовательских интерфейсов с использованием языка разметки XAML. Рассмотрены примеры реализации фрагментов проектов для реализации интерфейсов приложения WinRT.

    Вопросы

  • Какие языки используются для написания приложений для Windows Store?
  • Какие платформы используются для написания приложений для Windows Store?
  • В чем отличие языка XAML от других языков разметки?
  • Что собой представляют объектные элементы XAML?
  • Как записывается синтаксис объектных элементов XAML?
  • Как записывается синтаксис атрибутов объектного элемента?
  • Для чего используется синтаксис элементов свойств?
  • Приведите примеры синтаксис элементов свойств.
  • Приведите примеры наиболее распространенных расширений разметки, используемыми при программировании приложений WPF.
  • Страницы:

    Для реализации элементов интерфейса в Winodws 8 используются базовые элементы управления. В среде разработки Visual Studio имеется стандартный набор элементов управления, которые являются неотъемлемой частью любого интерфейса.

    Класс Control

    Класс является базовым для всех элементов управления, наделяя их базовыми свойствами Windows.UI.Xaml.Controls.Control. Начнем с трех свойств, которые определяют цветовые характеристики элементов управления:

  • Background - тут содержатся свойства фона, который, как правило, является поверхностью элемента управления;
  • Foreground - это свойство задает цвет текста, который может присутствовать в качестве содержимого элементов управления;
  • Opacity - это свойство (наследуется от UIElement) определяет прозрачность элемента управления. Прозрачность задается в процентах и варьируется от 0 до 1.
  • Свойства Background и Foreground могут принимать объект типа Brush, описывающий кисть. В главе, посвященной работе с графикой, мы рассмотрим доступные кисти, а сейчас представляем пример работы с самой простой кистью - SolidBrush:

    <StackPanel>
    <Button Background="#FFFF0000" Foreground="#FF00FF00"
    Content="Hello"></Button>
    <Button Background="Red" Foreground="LightGreen"
    Content="Hello"></Button>
    <Button Content="Hello">
    <Button.Background>
    <SolidColorBrush Color="Red"></SolidColorBrush>
    </Button.Background>
    <Button.Foreground>
    <SolidColorBrush Color="LightGreen"></SolidColorBrush>
    </Button.Foreground>
    </Button>
    </StackPanel> 

    В этом примере цвет задается сразу тремя способами: в шестнадцатеричном представлении, с использованием возможности конвертера значений свойств в XAML, явным созданием объекта SolidColorBrush. Аналогично свойства можно устанавливать и из C# кода:

    btn.Background = new SolidColorBrush(Colors.Red); 

    Тут Colors представляет собой специальный класс, определяющий несколько популярных цветов.

    Если используемый элемент работает с текстом, то для установки шрифта текста могут пригодиться следующие свойства:

  • FontFamily - задает имя шрифта, который Вы хотите использовать;
  • FontSize - размер шрифта в единицах Silverlight;
  • FontStyle - позволяет задать стиль шрифта, такой как Normal или Italic;
  • FontWeight - задает вес текста, например Bold;
  • FontStretch - используется для поддержки шрифтов OpenType, в частности позволяет сжимать или растягивать текст.
  • Ниже приведен пример использования перечисленных свойств, применяемых для установки надписи кнопки:

    <Button Background="Red" 
      Foreground="LightGreen" Content="Hello"
    FontFamily="Arial"
    FontSize="16"
    FontStyle="Italic"
    FontWeight="Bold">
    </Button> 

    Следующие несколько свойств позволяют задать размеры элемента, а также отступы от соседних элементов и от содержимого:

  • Width - длина элемента управления;
  • Height - ширина элемента управления;
  • Padding - расстояние от содержимого до границ элемента;
  • Margin - расстояние от каждой из границ до границ соседних элементов.
  • Кнопки

    В WinRT представлено большое количество кнопок. Среди них и новые типы, такие как ToggleSwitch. Вот краткое описание существующих кнопок:

  • Button - классическая кнопка, содержащая в качестве контента любой объект типа UIElement и инициирующая событие Click;
  • ToggleButton - тип кнопки, используемый для имитации эффекта залипания. Кнопка может быть в двух состояниях: нажатой и отпущенной. Чтобы обрабатывать изменение состояния кнопки, используется событие Checked;
  • RepeatButton - в отличие от классической кнопки, этот вид кнопки позволяет непрерывно генерировать событие Click, если кнопка остается нажатой, то есть удерживается пользователем в этом состоянии;
  • CheckBox - эта кнопка является прямым наследником ToggleButton и реализует простейший флажок. В отличие от ToggleButton, флажок можно устанавливать в промежуточное состояние, но только из кода и только если свойство IsThreeState установлено как true;
  • RadioButton - этот элемент управления полностью аналогичен CheckBox, но предоставляет возможность размещать целый набор элементов в группы, позволяя сделать единственный выбор;
  • HyperlinkButton - подобный тип кнопки чаще всего используется внутри текста для организации переходов на другие страницы. Кнопка по умолчанию выглядит как обычная гиперссылка в браузере;
  • ToggleSwitch - этот тип кнопки крайне интересен в условиях появления Touch-интерфейсов, так как с его помощью можно легко выполнять переключения состояния. Элемент очень напоминает CheckBox, но имеет совершенно уникальное представление.
  • Поскольку ToggleSwitch является новым элементом управления, хотелось бы продемонстрировать пример его работы. Код ниже задает такой элемент и позволяет выполнять переключение между двумя состояниями "Да" и "Нет":

     <ToggleSwitch OffContent="Нет" OnContent="Да"></ToggleSwitch> 

    Вот что мы увидим на экране:

    (рис 7.1)

    Этот элемент пришел с платформы Windows Phone и полностью оптимизирован для работы с помощью пальцев.

    Следующий пример, демонстрирующий создание группы элементов RadioButton:

    <StackPanel>
    <RadioButton Content="Choice 1" IsChecked="True"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    <RadioButton Content="Choice 1" IsChecked="False"
    GroupName="Group 1" Margin="5">
    </RadioButton>
    </StackPanel> 

    В результате работы кода мы увидим следующую картину:

    (рис 7.2)

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

    <Button MaxHeight="150" MaxWidth="200">
    <Button.Content>
    <MediaElement Source="Wildlife.wmv"></MediaElement>
    </Button.Content>
    </Button> 

    Текстовые элементы управления

    В Windows Runtime выделяют три типа базовых элементов управления, позволяющих редактировать текст:

  • TextBox - позволяет вводить простой текст в виде одной или нескольких строк;
  • PasswordBox - текст скрывается с помощью специальных символов;
  • RichEditBox - позволяет вводить форматированный текст. Если рассматривать свойства таких элементов, как TextBox и PasswordBox, можно выделить:
  • AcceptsReturn - позволяет выполнять перевод каретки при вводе текста;
  • IsReadOnly - определяет, будет ли текстовое поле доступно для ввода;
  • SelectedText - возвращает выделенный текст;
  • SelectionLength - позволяет получить или задать размер текущего выделения;
  • SelectionStart - позволяет получить или задать позицию символа, с которого нужно произвести выделение;
  • SelectionBackground - определяет цвет фона выделенного текста;
  • SelectionForeground - задает цвет шрифта выделенного текста;
  • TextWraping - определяет, будет ли текст переходить на другую строку, если он не помещается в видимой части одной строки.
  • <TextBox AcceptsReturn="True" TextWrapping="Wrap"
       Width="300" Height="200">
         </TextBox> 

    Элементу TextBox можно противопоставить элемент управления TextBlock, задачей которого является отображение текста. Оба эти элемента способны удовлетворить все нужды разработчика в редактировании и отображении простого текста.

    Если же говорить о форматированном тексте, тут требуется применять RichTextEdit и RichTextBlock. Если первый элемент позволяет ввести и редактировать форматированный текст, то второй - отображает только чтение. Оба элемента являются контейнерами для других элементов. Так, основным наполнением этих элементов выступает набор элементов Paragraph, которые описывают параграфы текстового документа. В свою очередь, параграф может включать набор из следующих элементов:

  • Run - задает обычный текст;
  • Span - служит для группировки других элементов;
  • Bold - определяет жирное начертание символов;
  • LineBreak -задает переход на другую строку;
  • Italic - определяет рукописное начертание символов;
  • Underline - выделяет текст подчеркиванием;
  • HyperLink - создает гиперссылку, которая становится активной только в режиме ReadOnly элемента RichTextArea;
  • InlineUIContainer - позволяет вставить в документ любой из элементов, порожденных UIElement.
  • Ниже пример элемента RichTextBlock, отображающего текст с минимальным форматированием:

    <RichTextBlock HorizontalAlignment="Left"
    Name="rArea" VerticalAlignment="Top"
    Height="300" Width="400" >
    <Paragraph>
    <Bold>This is a bold text</Bold>
    <LineBreak></LineBreak>
    <Underline>This is an underline text</Underline>
    <LineBreak></LineBreak>
    <Italic>This is an italic text</Italic>
    <LineBreak></LineBreak>
    This is a button:
    <InlineUIContainer>
    <Button Content="Button"></Button>
    </InlineUIContainer>
    </Paragraph>
    </RichTextBlock> 

    В результате на экране отобразится следующий контент:

    (рис 7.3)

    Естественно, создавать и заполнять RichTextBlock можно и с помощью кода на C. Вот небольшой пример кода:

    Bold b = new Bold();
    b.Inlines.Add("This is a bold text");
    Italic i = new Italic();
    i.Inlines.Add("This is an italic text");
    Underline u = new Underline();
    u.Inlines.Add("This is an underlined text");
    Paragraph myPar = new Paragraph();
    myPar.Inlines.Add(b);
    myPar.Inlines.Add(new LineBreak());
    myPar.Inlines.Add(i);
    myPar.Inlines.Add(new LineBreak());
    myPar.Inlines.Add(u);
    rArea.Blocks.Add(myPar); 

    Понятие стиля

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

    Рассмотрим небольшой пример, демонстрирующий создание четырех кнопок.

    <StackPanel>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 1" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 2" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 3" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    <Button Width="100" Height="50"
    Background="Green"
    Content="Button 4" Margin="5" FontFamily="Arial"
    FontSize="12" FontWeight="Bold"
    Foreground="Blue" BorderThickness="3">
    </Button>
    </StackPanel> 

    Таким образом, создав всего четыре кнопки, продублировали множество строк кода. Это не только значительно увеличивает размер файла, но и ведет к возникновению ошибок. Ведь указав неверно один атрибут, можно испортить внешний вид всего интерфейса.

    Для выделения общих свойств в отдельный стиль в XAML используется специальный элемент Style. Поскольку он не должен входить в дерево элементов, а лишь задает набор свойств группы элементов, то располагать его следует внутри ресурсов приложения, страницы или отдельного элемента (в зависимости от области применения).

    Продемонстрируем работу элемента Style на примере. Для этого определим следующий блок кода сразу после открывающего элемента:

    Page.
    <Page.Resources>
    <Style x:Key="buttonStyle" TargetType="Button">
    <Setter Property="Background" Value="Green"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="FontFamily" Value="Arial"></Setter>
    <Setter Property="FontSize" Value="12"></Setter>
    <Setter Property="FontWeight" Value="Bold"></Setter>
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="BorderThickness" Value="3"></Setter>
    </Style>
    </Page.Resources> 

    Как видите, чтобы задать стиль, необходимо указать ключ и тип элементов, для которых будет применяться стиль. Ключ используется для поиска необходимого стиля, а TargetType определяет, к каким элементам применим стиль. Далее с помощью набора элементов Setter мы перечислили все свойства и их значения. Код XAML интерфейса выглядит следующим образом.

    <StackPanel>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 1">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 2">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 3">
    </Button>
    <Button Width="100" Height="50"
    Style="{StaticResource buttonStyle}" Content="Button 4">
    </Button>
    </StackPanel> 

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

    <Page.Resources>
    <Style TargetType="Button">
    <Setter Property="Background" Value="Green"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="FontFamily" Value="Arial"></Setter>
    <Setter Property="FontSize" Value="12"></Setter>
    <Setter Property="FontWeight" Value="Bold"></Setter>
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="BorderThickness" Value="3"></Setter>
    </Style>
    </Page.Resources>
    <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
    <StackPanel>
    <Button Width="100" Height="50"
    Content="Button 1">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 2">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 3">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 4">
    </Button>
    </StackPanel>
    </Grid> 

    Стили представляют собой очень мощный механизм, позволяющий сделать не только Ваше приложение в едином формате, но и придать общность большинству запускаемых приложений. Чтобы у разработчика была возможность создавать страницы, придерживаясь единого стиля, Visual Studio включает в любой проект файл StandardStyles.xaml, который определяет набор стандартных стилей на все случаи жизни. Так, попробуйте модифицировать код выше, прописав кнопкам стиль BackButtonStyle.

    <StackPanel>
    <Button Width="100" Height="50"
    Content="Button 1" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 2" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 3" Style="{StaticResource BackButtonStyle}">
    </Button>
    <Button Width="100" Height="50"
    Content="Button 4" Style="{StaticResource BackButtonStyle}">
    </Button>
    </StackPanel> 

    В результате работы кода на экране появится следующая картина. Как видно из рисунка, цвет одной из кнопок немного отличается. Дело в том, что стиль определяет не только внешний вид кнопки, но и ее поведение при наведении мышью, выборе и т. д. Все это возможно благодаря специальным свойствам, позволяющим задавать шаблоны элементов управления.

    BasedOn-стили

    XAML в Windows Runtime поддерживает и BasedOn-стили. Это позволяет задать общие стили применительно к базовым классам для общей группы элементов управления (или для конкретного типа элементов управления) и определить дополнительные стили путем наследования. Ниже приведен пример BasedOn-стиля.

    <Style x:Key="baseStyle" TargetType="Button" >
    <Setter Property="Width" Value="100"></Setter>
    </Style>
    <Style x:Key="btnStyleRus"
    BasedOn="{StaticResource baseStyle}" TargetType="Button">
    <Setter Property="Foreground" Value="Blue"></Setter>
    <Setter Property="Content" Value="Кнопка"></Setter>
    </Style>
    <Style x:Key="btnStyle"
    BasedOn="{StaticResource baseStyle}" TargetType="Button">
    <Setter Property="Foreground" Value="Green"></Setter>
    <Setter Property="Content" Value="Button"></Setter>
    </Style> 

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

    Ресурсы

    Выше говорилось о возможности создания стилей. Которые, как было отмечено, не должны входить в дерево XAML-элементов. Все стили записывали внутри свойства Resources, принадлежащего объекту Page. Подобное свойство есть у всех объектов XAML, порожденных от FrameworkElement, а также у объекта приложения (Application). Благодаря ресурсам разработчик может сохранять стили и другие части XAML-кода до востребования. Так, в ресурсы можно выделять объекты некоторых типов, стили, шаблоны данных и др. Фактически, свойство Resources ссылается на некий словарь, который может быть доступен как из кода, так и из XAML.

    Если используются ресурсы на уровне приложения, то доступ к ресурсу может быть осуществлён лишь по ключу, вне зависимости от того, в каком из родительских элементов объявлен ресурс. Если же ресурс был объявлен в одном из дочерних элементов, то он не может использоваться родительскими элементами.

    Рассмотрим небольшой пример.

    <Page.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </Page.Resources>
    <StackPanel>
    <Button Width="100" Height="50"
    Background="{StaticResource myBrush}"
    Content="Button 1" Margin="5">
    </Button>
    </StackPanel>

    Здесь определили в роли ресурса градиентную кисть, указав в качестве ключа (он же является именем) myBrush. Данный ключ будет использоваться для доступа к ресурсу. Как Вы могли заметить, доступ к ресурсу определяется с помощью расширения разметки StaticResource. Достаточно указать имя ключа в качестве параметра.

    В примере выше разместили ресурсы внутрь элемента Page, который является контейнером для интерфейса. Это обеспечивает видимость ресурсов для любого дочернего элемента. Если мы хотим ограничить область видимости, то ресурсы можно разместить в любом из дочерних элементов, например в StackPanel.

    <StackPanel>
    <StackPanel.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </StackPanel.Resources>
    <Button Width="100" Height="50"
    Background="{StaticResource myBrush}"
    Content="Button 1" Margin="5">
    </Button>
    </StackPanel> 

    Таким образом, для конечного элемента управления нет никакой разницы, где находятся ресурсы. Главное, чтобы они были в области видимости элемента, а доступ к ним осуществляется по одинаковой схеме.

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

    <Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application4">
    <Application.Resources>
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </Application.Resources>
    </Application> 

    Выделение ресурсов объектов в отдельные файлы

    Ресурсы можно хранить в отдельных файлах и собирать в нужном месте с помощью элемента ResourceDictionary. Вынесем кисть из предыдущего примера в отдельный файл RD1.xaml.

    <ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <LinearGradientBrush x:Key="myBrush">
    <GradientStop Color="Red" Offset="0"></GradientStop>
    <GradientStop Color="Green" Offset="1"></GradientStop>
    </LinearGradientBrush>
    </ResourceDictionary> 

    Для подключения внешнего файла к интерфейсу приложения используется все тот же ResourceDictionary.

    <Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application4">
    <Application.Resources>
    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="RD1.xaml" />
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    </Application.Resources>
    </Application> 

    Если у вас несколько файлов - не проблема. Перечислите их все. Обратите внимание, что стандартный файл StandardStyles.xaml как раз и оформлен как внешний файл ресурсов, который подключается внутри файла App.xaml.

    Если Вы хотите подключить файл с ресурсами в ресурсы одного из элементов, то это делается аналогичным образом.

    Краткие итоги

    Рассмотрен процесс создания пользовательских интерфейсов с использованием языка разметки XAML. Рассмотрены примеры реализации фрагментов проектов для реализации интерфейсов приложения WinRT.

    Вопросы

  • Какие языки используются для написания приложений для Windows Store?
  • Какие платформы используются для написания приложений для Windows Store?
  • В чем отличие языка XAML от других языков разметки?
  • Что собой представляют объектные элементы XAML?
  • Как записывается синтаксис объектных элементов XAML?
  • Как записывается синтаксис атрибутов объектного элемента?
  • Для чего используется синтаксис элементов свойств?
  • Приведите примеры синтаксис элементов свойств.
  • Приведите примеры наиболее распространенных расширений разметки, используемыми при программировании приложений WPF.
  • Вернуться к учебному плану