Что такое XAML?
XAML — это аббревиатура от расширяемого языка разметки приложений. Это язык разметки, основанный на XML, и его назначение и философия очень похожи на HTML. Каждый элемент управления, который может быть размещен на странице, будь то кнопка, текстовое поле или пользовательские элементы управления, идентифицируется определенным тегом XML. Как и XML, структура является иерархической; Вы можете разместить теги внутри других тегов. Например, эта иерархическая структура позволяет определять макет страницы благодаря некоторым элементам управления, которые действуют как контейнер для других элементов управления, таких как Grid
или StackPanel
.
Ниже приведен пример XAML, который определяет страницу Windows Phone:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<phone:PhoneApplicationPage
x:Class=»FirstApp.MainPage»
xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
xmlns:phone=»clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone»
xmlns:shell=»clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone»
xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
mc:Ignorable=»d»
FontFamily=»{StaticResource PhoneFontFamilyNormal}»
FontSize=»{StaticResource PhoneFontSizeNormal}»
Foreground=»{StaticResource PhoneForegroundBrush}»
SupportedOrientations=»Portrait» Orientation=»Portrait»
shell:SystemTray.IsVisible=»True»>
<Grid x:Name=»LayoutRoot» Background=»Transparent»>
<Grid.RowDefinitions>
<RowDefinition Height=»Auto»/>
<RowDefinition Height=»*»/>
</Grid.RowDefinitions>
<Grid x:Name=»ContentPanel» Grid.Row=»1″ Margin=»12,0,12,0″>
<StackPanel>
<TextBlock Text=»This is a page» />
</StackPanel>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
|
PhoneApplicationPage
— это базовый класс страницы Windows Phone. Как видите, все остальные элементы управления находятся внутри него. Обратите внимание также на атрибут x:Class
; он идентифицирует, какой класс code-behind связан с этой страницей. В этом примере код, который может взаимодействовать со страницей, будет храниться в классе MainPage
который является частью пространства имен FirstApp
. Мы можем увидеть этот класс, просто нажав на черную стрелку рядом с файлом XAML в Solution Explorer. Вы увидите другой файл с тем же именем, что и XAML, плюс расширение .cs
.
Давайте начнем анализировать этот простой XAML, чтобы представить некоторые ключевые понятия, такие как пространства имен и ресурсы.
Пространства имен
Вы уже должны быть знакомы с пространствами имен; это способ структурировать ваш код, назначая логический путь вашему классу.
По умолчанию Visual Studio назначает пространства имен, используя ту же структуру папок проекта. Это означает, что, например, если у вас есть класс с именем MyClass
хранящийся в файле в папке Classes
, по умолчанию полное пространство имен вашего класса будет Classes.MyClass
.
Пространства имен в XAML работают точно так же. Элементы управления XAML, в конце концов, являются классами, которые являются частью вашего проекта, поэтому вы должны указать странице, где они могут их найти. На стандартной странице вы можете увидеть множество примеров объявлений пространства имен:
1
|
xmlns:phone=»clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone»
|
Каждое пространство имен начинается с префикса xmlns
, который является стандартным пространством имен XML, за которым следует пользовательский префикс (в данном примере это phone
). Этот префикс очень важен, потому что он будет использоваться на остальной части страницы для добавления элементов управления. Затем мы определяем полное пространство имен, которое содержит элементы управления. Если класс является частью нашего проекта, достаточно указать только пространство имен; в противном случае нам также нужно определить, какая сборка (то есть имя DLL) содержит класс.
В предыдущем примере мы хотим включить элементы управления и ресурсы на нашей странице, которые определены в пространстве имен Microsoft.Phone.Controls
, которое включено в библиотеку Microsoft.Phone.dll
.
Класс PhoneApplicationPage
дает вам пример того, как использовать пространство имен. Поскольку класс PhoneApplicationPage
является частью пространства имен Microsoft.Phone.Controls
, мы должны добавить префикс phone
к тегу, чтобы использовать его:
1
|
<phone:PhoneApplicationPage />
|
Очень важно понимать, как работают пространства имен в XAML, потому что нам нужно будет объявлять их каждый раз, когда мы используем сторонние элементы управления (которые мы создали самостоятельно или являемся частью внешней библиотеки) или ресурсы, такие как конвертеры.
Свойства и События
Каждый элемент управления можно настроить двумя способами: путем настройки свойств и действий. Оба идентифицируются атрибутами тега XAML, но они имеют две разные цели.
Свойства используются для изменения внешнего вида или поведения элемента управления. Обычно свойство просто устанавливается путем присвоения значения определенному атрибуту. Например, если мы хотим присвоить значение свойству Text
элемента управления TextBlock
, мы можем сделать это следующим образом:
1
|
<TextBlock Text=»This is a text block» />
|
Существует также расширенный синтаксис, который можно использовать в случае сложного свойства, которое нельзя определить с помощью простой строки. Например, если нам нужно установить изображение в качестве фона элемента управления, нам нужно использовать следующий код:
1
2
3
4
5
|
<Grid>
<Grid.Background>
<ImageBrush ImageSource=»/Assets/Background.png» />
</Grid.Background>
</Grid>
|
Сложные свойства устанавливаются с помощью вложенного тега с именем элемента управления и именем свойства, разделенными точкой (для установки свойства Background
элемента управления Grid
мы используем синтаксис Grid.Background
).
Одним из важных свойств, которое совместно используется каждым элементом управления, является x:Name
, которое представляет собой строку, однозначно определяющую элемент управления на странице. Вы не можете иметь два элемента управления с одинаковым именем на одной странице. Установка этого свойства очень важна, если вам нужно взаимодействовать с элементом управления в коде — вы сможете ссылаться на него, используя его имя.
События — это способ управления взаимодействием пользователей с элементом управления. Одним из наиболее часто используемых является Tap
, который срабатывает, когда пользователи нажимают на элемент управления.
1
|
<Button Tap=»OnButtonClicked» />
|
Когда вы определяете действие, Visual Studio автоматически предложит вам создать обработчик событий , который является методом (объявленным в коде), который выполняется при запуске события.
1
2
3
4
|
private void OnButtonClicked(object sender, GestureEventArgs e)
{
MessageBox.Show(«Hello world»);
}
|
В предыдущем примере мы показываем классическое сообщение «Hello world» пользователям, когда кнопка нажата.
Ресурсы
Как и в HTML, мы можем определить стили CSS, которые можно использовать в разных частях сайта или на странице. XAML представил концепцию ресурсов, которые могут применяться к различным элементам управления в приложении.
По сути, каждый элемент управления XAML поддерживает тег Resources
: благодаря иерархической структуре каждый другой вложенный элемент управления сможет использовать его. В реальном мире есть два общих места для определения ресурса: на уровне страницы и приложения.
Ресурсы страницы определены на одной странице и доступны всем элементам управления, которые являются частью этой страницы. Они помещаются в определенное свойство, которое называется Resources
класса PhoneApplicationPage
.
1
2
3
|
<phone:PhoneApplicationPage.Resources>
<!— you can place resources here —>
</phone:PhoneApplicationPage.Resources>
|
Ресурсы приложения , напротив, доступны по всему миру, и их можно использовать на любой странице приложения. Они определены в файле App.xaml
, и стандартный шаблон уже содержит необходимое определение.
1
2
3
|
<Application.Resources>
<!— here you can place global resources —>
</Application.Resources>
|
Каждый ресурс однозначно идентифицируется именем, которое назначается с помощью свойства x:Key
. Чтобы применить ресурс к элементу управления, нам нужно ввести понятие расширений разметки . Это специальные расширения, которые позволяют нам применять различные варианты поведения, которые в противном случае потребовали бы некоторого кода для нормальной работы. В мире XAML существует множество расширений разметки, и одно из них, необходимое для применения ресурса, называется StaticResource
. Вот пример того, как его использовать:
1
|
<TextBlock Text=»MY APPLICATION» Style=»{StaticResource PhoneTextNormalStyle}» />
|
В этом примере ресурс применяется к свойству Style
путем включения ключевого слова StaticResource
в фигурные скобки, за которым следует имя ресурса, которое является значением свойства x:Key
.
Ресурсы также могут быть определены во внешнем файле с именем ResourceDictionary
если вы хотите лучше организовать свой проект. Для этого щелкните правой кнопкой мыши свой проект в Visual Studio, нажмите « Добавить» > « Новый элемент» и выберите файл XML . Дайте файлу имя, которое заканчивается расширением .xaml, и включите следующее определение:
1
2
3
4
5
6
7
|
<ResourceDictionary
xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»>
<!— put resources here —>
</ResourceDictionary>
|
Теперь вы можете добавить его в свой проект, объявив его в App.xaml
:
1
2
3
4
5
6
7
|
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source=»Assets/Resources/Styles.xaml» />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
|
Обратите внимание на свойство MergedDictionaries
: здесь должны быть объявлены все файлы внешних ресурсов. Таким образом, они будут автоматически объединены, и каждый ресурс, объявленный в каждом внешнем файле, будет доступен для каждой страницы, как если бы они были объявлены встроенными.
Давайте теперь посмотрим подробно, какие ресурсы являются наиболее важными.
Стили
Стили XAML работают так же, как и стили CSS: вы можете определять значения различных свойств вместе в одном стиле, который можно применять к нескольким элементам управления, чтобы они все использовали один и тот же макет. Вот как выглядит определение стиля:
1
2
3
4
|
<Style x:Key=»CustomText» TargetType=»TextBlock»>
<Setter Property=»FontSize» Value=»24″ />
<Setter Property=»FontWeight» Value=»Bold» />
</Style>
|
Стиль определяется тегом Style
, который имеет два важных атрибута: x:Key
, имя стиля и TargetType
, тип элементов управления, который подходит для этого стиля.
Внутри тега Style
вы можете разместить столько тегов Setter
сколько захотите. Каждый идентифицирует свойство элемента управления, которое вы хотите изменить. Каждый тег Setter
нуждается в двух атрибутах: Property
— это свойство элемента управления, которое вы хотите изменить, и Value
— это значение, которое вы хотите присвоить свойству.
Стиль, определенный в предыдущем примере, можно применить к любому TextBlock
управления TextBlock
. Его цель — изменить размер шрифта до 24 и применить жирный стиль к тексту.
Существуют также специальные типы стилей, называемые неявными стилями . Они определяются так же, как и стили в предыдущем примере, за исключением того, что отсутствует атрибут x:Key
. В этом случае стиль автоматически применяется к каждому TargetType
управления, который соответствует значению свойства TargetType
, в соответствии с областью, в которой был определен стиль. Если стиль установлен как ресурс страницы, он будет применяться только к элементам управления страницы; если стиль установлен как ресурс приложения, он будет применяться ко всем элементам управления в приложении.
Шаблоны данных
Шаблоны данных — это особый тип ресурса, который можно применять к элементу управления для определения его внешнего вида. Шаблоны данных часто используются с элементами управления, которые могут отображать коллекции элементов, например ListBox
или LongListSelector
.
В следующем примере показан шаблон данных:
1
2
3
4
5
6
7
8
|
<DataTemplate x:Key=»PeopleTemplate»>
<StackPanel>
<TextBlock Text=»Name» />
<TextBlock Text=»{Binding Path=Name}» />
<TextBlock Text=»Surname» />
<TextBlock Text=»{Binding Path=Surname}» />
</StackPanel>
</DataTemplate>
|
Шаблон данных просто содержит XAML, который будет использоваться для визуализации определенного элемента. Если, например, мы применим этот шаблон данных к свойству ItemTemplate
элемента управления ListBox
, результатом будет повторение определенного XAML для каждого элемента в коллекции (на данный момент просто игнорируем расширение разметки Binding
; мы Я буду иметь дело с этим позже, когда мы поговорим о привязке данных).
Как и для любого другого ресурса, шаблоны данных могут быть назначены свойству с помощью расширения разметки StaticResource
.
1
|
<ListBox ItemTemplate=»{StaticResource PeopleTemplate}» />
|
Анимации
XAML — мощный язык, потому что он позволяет нам делать больше, чем просто создавать макет приложений. Одной из наиболее интересных функций является функция анимации, которую можно создать с помощью Storyboard
управления « Storyboard
.
Элемент управления Storyboard
может использоваться для определения различных типов анимации:
-
DoubleAnimation
, которая может использоваться для изменения числового значения свойства (например,Width
илиFontSize
). -
ColorAnimation
, которая может использоваться для взаимодействия со свойствами, которые определяют цвет (как внутриSolidColorBrush
). -
PointAnimation
, которую можно применять к свойствам, которые определяют координату точки.
Следующий пример кода определяет анимацию:
1
2
3
4
5
6
7
|
<Storyboard x:Name=»Animation»>
<DoubleAnimation Storyboard.TargetName=»RectangleElement»
Storyboard.TargetProperty=»Width»
From=»200″
To=»400″
Duration=»00:00:04″ />
</Storyboard>
|
Первые два свойства унаследованы от Storyboard
управления Storyboard
: Storyboard.TargetName
используется для задания имени элемента управления, который мы собираемся анимировать, а Storyboard.TargetProperty
— это свойство, значение которого мы собираемся изменить во время анимации.
Далее мы определяем поведение анимации: начальное значение (свойство From
), конечное значение (свойство To
) и продолжительность (свойство Duration
). Поведение, определенное в предыдущем примере, анимирует элемент управления Rectangle
, увеличив его ширину с 200 до 400 в течение 4 секунд.
Мы также можем более глубоко контролировать анимацию, используя вариант UsingKeyFrames
доступный для каждого типа анимации:
1
2
3
4
5
6
7
8
|
<Storyboard x:Name=»Animation»>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=»RectangleElement»
Storyboard.TargetProperty=»Width»>
<LinearDoubleKeyFrame KeyTime=»00:00:00″ Value=»200″ />
<LinearDoubleKeyFrame KeyTime=»00:00:02″ Value=»250″ />
<LinearDoubleKeyFrame KeyTime=»00:00:04″ Value=»500″ />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
|
Таким образом, вы сможете контролировать время анимации. В предыдущем примере тип анимации тот же (это DoubleAnimation
), но мы можем установить для определенного времени значение, которое будет применяться с LinearDoubleKeyFrame
тега LinearDoubleKeyFrame
.
В предыдущем примере в качестве значения Width
элемента управления « Rectangle
задано значение 200. Затем через две секунды оно увеличивается до 250, а через четыре секунды устанавливается на 500.
Облегчение анимации
Еще один способ создания анимации — это использование математических формул, которые могут применять реалистичное поведение к объекту, например, отскакивание или ускорение и замедление. Вы можете достичь того же результата, используя ключевые кадры, но это потребует много работы. По этой причине инфраструктура анимации предлагает набор предопределенных функций замедления, которые можно легко применить к анимации.
Чтобы добавить функцию замедления, вам просто нужно установить свойство анимации EasingFunction
, как показано в следующем примере:
1
2
3
4
5
6
7
8
9
|
<Storyboard x:Name=»EasingAnimation»>
<PointAnimation From=»0,0″ To=»0, 200″ Duration=»00:00:3″
Storyboard.TargetName=»Circle»
Storyboard.TargetProperty=»Center»>
<PointAnimation.EasingFunction>
<BounceEase Bounces=»2″ EasingMode=»EaseOut» />
</PointAnimation.EasingFunction>
</PointAnimation>
</Storyboard>
|
После того как вы определили обычную анимацию (в данном примере это PointAnimation
которая перемещает объект Ellipse
из координат (0, 0) в (0, 200)), вы можете установить свойство EasingFunction
с помощью одной из доступных функций замедления. , В этом примере показано, как использовать функцию BounceEase
, которую можно использовать для применения эффекта отскакивания к объекту (количество отскоков выполняется с Bounces
свойства Bounces
).
Другие доступные функции ослабления:
-
BackEase
, который немного убирает движение анимации до ее запуска. -
CircleEase
, который применяет круговую функцию к анимации ускорения. -
ElasticEase
, который создает анимацию, напоминающую колеблющуюся пружину.
Официальная документация MSDN содержит полный список доступных функций замедления.
Как управлять анимацией
Анимации рассматриваются как ресурсы. Они могут быть определены как локальные ресурсы, ресурсы страницы или ресурсы приложения. В отличие от традиционных ресурсов, элементы управления Storyboard
идентифицируются свойством x:Name
, как обычный элемент управления.
В следующем примере показана анимация, заданная как ресурс страницы:
1
2
3
4
5
6
7
8
9
|
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name=»Animation»>
<DoubleAnimation Storyboard.TargetName=»RectangleElement»
Storyboard.TargetProperty=»Width»
From=»200″
To=»400″
Duration=»00:00:04″ />
</Storyboard>
</phone:PhoneApplicationPage.Resources>
|
Благодаря уникальному идентификатору вы сможете управлять анимацией в коде. Каждый объект Storyboard
предлагает множество методов для управления им, таких как Begin()
, Stop()
или Resume()
. В следующем коде вы видите обработчики событий, назначенные двум кнопкам, которые используются для запуска и остановки анимации:
1
2
3
4
5
6
7
8
9
|
private void OnStartClicked(object sender, GestureEventArgs e)
{
Animation.Begin();
}
private void OnStopClicked(object sender, GestureEventArgs e)
{
Animation.Stop();
}
|
Привязка данных
Привязка данных является одной из самых мощных функций, предоставляемых XAML. Благодаря привязке данных вы сможете создать канал связи между элементом пользовательского интерфейса и различными источниками данных, которые могут быть другим элементом управления или свойством в одном из ваших классов. Более того, привязка данных тесно связана с системой уведомлений XAML (о которой мы расскажем позже), так что каждый раз, когда вы что-то изменяете в своем объекте, элемент управления, отображающий его, будет автоматически обновляться для отражения изменений и отображения нового значения.
Когда вы создаете канал связи, используя привязку данных, вы определяете source
(который содержит данные для отображения) и target
(который заботится об отображении значения). По умолчанию канал привязки установлен в режим OneWay
. Это означает, что при изменении source
target
обновляется для отображения нового значения, а не наоборот. Если нам нужно создать двусторонний канал связи (например, поскольку целью является элемент управления TextBox
и нам нужно перехватить новое значение, вставленное пользователем), мы можем установить свойство Mode
привязки в TwoWay
.
1
|
<TextBox Text=»{Binding Path=Name, Mode=TwoWay}» />
|
Почти каждый элемент управления в XAML может участвовать в привязке данных. Фактически большинство свойств, доступных для элемента управления, являются dependency properties
. Помимо предоставления базовых возможностей чтения и записи, это специальные свойства, которые поддерживают уведомления, чтобы они могли уведомлять другую сторону канала о том, что что-то изменилось.
В следующем примере показано, как привязка данных может использоваться для создания канала между двумя элементами управления XAML:
1
2
3
4
|
<StackPanel>
<Slider x:Name=»Volume» />
<TextBlock x:Name=»SliderValue» Text=»{Binding ElementName=Volume, Path=Value}» />
</StackPanel>
|
Первое, на что нужно обратить внимание, это то, что для применения привязки нам нужно использовать другое расширение разметки , называемое Binding
. С помощью этого выражения мы соединяем свойство Text
элемента управления TextBlock
(цель) со свойством Value
элемента управления Slider
с именем Volume
(источник).
Поскольку и Text
и Value
являются зависимыми свойствами, при каждом перемещении ползунка выбранное значение будет автоматически отображаться на экране в элементе управления TextBlock
.
Связывание данных с объектами
Одной из самых мощных функций привязки данных является возможность связывать элементы управления с объектами, которые являются частью вашего кода. Однако, во-первых, нам нужно представить концепцию DataContext
. DataContext
— это свойство, которое доступно почти для каждого элемента управления и может использоваться для определения его связующего контекста, который также автоматически наследуется каждым вложенным элементом управления. Когда вы определяете объект как DataContext
, элемент управления и все его дочерние элементы будут иметь доступ ко всем его свойствам.
Давайте рассмотрим пример, который поможет вам лучше понять, как это работает. Допустим, у вас есть класс, который представляет человека:
1
2
3
4
5
|
public class Person
{
public string Name { get;
public string Surname { get;
}
|
Наша цель — показать информацию о человеке, использующем этот класс. Вот как мы можем сделать это, используя привязку данных. Во-первых, давайте посмотрим на код позади:
1
2
3
4
5
6
7
8
|
public MainPage()
{
InitializeComponent();
Person person = new Person();
person.Name = «Matteo»;
person.Surname = «Pagani»;
Author.DataContext = person;
}
|
Когда страница инициализируется, мы создаем новый объект Person
и устанавливаем значение для свойств Name
и Surname
. Затем мы устанавливаем этот новый объект как DataContext
элемента управления Author
. Давайте посмотрим на странице XAML элемент управления Author
и то, как отображаются свойства Name
и Surname
:
1
2
3
4
5
6
|
<StackPanel x:Name=»Author»>
<TextBlock Text=»Name» />
<TextBlock Text=»{Binding Path=Name}» />
<TextBlock Text=»Surname» />
<TextBlock Text=»{Binding Path=Surname}» />
</StackPanel>
|
Author
— это имя, назначенное StackPanel
управления StackPanel
, который является контейнером, который мы поместили в различные элементы управления TextBlock
. В предыдущем примере мы снова видим расширение разметки Binding
в действии, на этот раз с другим атрибутом: Path
. Мы используем его, чтобы сообщить XAML, какое свойство текущего DataContext
отображать. Поскольку DataContext
наследуется от StackPanel
управления StackPanel
, каждый TextBlock
имеет доступ к свойствам объекта Person
мы создали в коде позади. Обратите внимание, что атрибут Path
является необязательным. Два следующих утверждения абсолютно одинаковы:
1
2
|
<TextBlock Text=»{Binding Path=Name}» />
<TextBlock Text=»{Binding Name}» />
|
Интерфейс INotifyPropertyChanged
Предыдущий код имеет недостаток. Все работает нормально, но если вы измените значение одного из свойств Name
или Surname
во время выполнения, пользовательский интерфейс не будет обновлен для отображения нового значения. Причина в том, что Name
и Surname
являются простыми свойствами, поэтому они не могут уведомить пользовательский интерфейс о том, что что-то изменилось, в отличие от свойств зависимости. Для этого сценария платформа XAML представила интерфейс INotifyPropertyChanged
который может быть реализован объектами, которые должны удовлетворять этому требованию уведомления. Вот как класс Person
может быть изменен для реализации этого интерфейса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class Person: INotifyPropertyChanged
{
private string _name;
private string _surname;
public string Name
{
get { return _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public string Surname
{
get { return _surname;
set
{
_surname = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
|
Класс теперь реализует интерфейс INotifyPropertyChanged
, что позволяет нам поддерживать обработчик событий (называемый PropertyChangedEventHandler
), который запускается каждый раз, когда изменяется значение свойства. Класс также реализует метод OnPropertyChanged()
который действует как оболочка обработчика событий и должен вызываться при изменении свойства.
Нам также нужно изменить наши свойства. Каждый раз, когда вызывается набор свойств (то есть назначено новое значение), мы OnPropertyChanged()
метод OnPropertyChanged()
. В результате каждый элемент управления, связанный со свойством, будет уведомлен об изменении и соответствующим образом обновит свой визуальный статус.
Привязка данных и сборы
Связывание данных особенно полезно, когда вам приходится иметь дело с коллекциями объектов, такими как массивы или списки (в основном, с типами коллекций каждой платформы, которые реализуют интерфейс IEnumerable
). Почти каждый элемент управления, который поддерживает коллекции, которые наследуются от класса ItemsControl
(например, ListBox
или LongListSelector
), имеет свойство ItemsSource
, которое может быть непосредственно назначено списку.
Вы можете контролировать, как каждый объект коллекции будет отображаться, используя свойство ItemTemplate
. Как мы уже видели, когда говорили о шаблонах данных, это свойство позволяет нам указать, какой XAML использовать для отображения объекта.
Теперь, когда мы поговорили о привязке данных, добавим еще один важный момент. В примере кода, который мы использовали для отображения шаблонов данных, мы включили некоторые обязательные выражения для отображения имени и фамилии человека.
1
2
3
4
5
6
7
8
|
<DataTemplate x:Key=»PeopleTemplate»>
<StackPanel>
<TextBlock Text=»Name» />
<TextBlock Text=»{Binding Path=Name}» />
<TextBlock Text=»Surname» />
<TextBlock Text=»{Binding Path=Surname}» />
</StackPanel>
</DataTemplate>
|
Когда вы устанавливаете коллекцию как ItemSource
, каждый объект, который является ее частью, становится DataContext
ItemTemplate
. Если, например, свойство ItemsSource
объекта ListBox
связано с коллекцией, тип которой — List<Person>
, элементы управления, включенные в ItemTemplate
, смогут получить доступ ко всем свойствам класса Person
.
Это реальное значение предыдущего примера кода: для каждого объекта Person
, являющегося частью коллекции, мы собираемся отобразить значения свойств Name
и Surname
.
Другая важная часть головоломки при работе с коллекциями — это класс ObservableCollection<T>
. Он действует как обычная коллекция, поэтому вы можете легко добавлять, удалять и перемещать объекты. Под капотом он реализует интерфейс INotifyPropertyChanged
так что каждый раз, когда коллекция изменяется, пользовательский интерфейс получает уведомление. Таким образом, каждый раз, когда мы манипулируем коллекцией (например, добавляем новый элемент), связанный с ним элемент управления будет автоматически обновляться для отражения изменений.
Преобразователи
Конвертеры играют важную роль в привязке данных. Иногда, на самом деле, вам нужно изменить исходные данные, прежде чем они будут отправлены в цель. Типичным примером является случай, когда вам приходится иметь дело со свойствами DateTime
. Класс DateTime
содержит полное представление даты, включая часы, минуты, секунды и миллисекунды. Однако в большинстве случаев вам не нужно отображать полное представление — часто просто достаточно даты.
Здесь конвертеры пригодятся. Вы можете изменить данные (или, как показано в следующем примере, применить другое форматирование) перед отправкой их в элемент управления, который будет отображать их с помощью привязки данных.
Чтобы создать конвертер, вам нужно добавить новый класс в ваш проект (щелкните правой кнопкой мыши в Visual Studio, выберите « Добавить» > « Класс» ), и он должен наследоваться от интерфейса IValueConverter
. Ниже приведен пример конвертера:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class DateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
DateTime date = (DateTime)value;
return date.ToShortDateString();
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
DateTime date = DateTime.Parse(value.ToString());
return date;
}
return DateTime.Now;
}
}
|
Когда вы поддерживаете интерфейс IValueConverter
, вы вынуждены реализовать два метода:
-
Convert()
— это метод, который вызывается при отправке данных из источника в цель. -
ConvertBack()
делает обратное — он вызывается, когда данные из цели отправляются обратно в источник.
В большинстве случаев достаточно реализовать метод Convert()
который поддерживается каждой привязкой. ConvertBack()
метод ConvertBack()
поддерживается только при TwoWay
привязки TwoWay
.
Оба метода получают важную информацию в качестве входных параметров:
- Значение, возвращаемое из источника привязки (которым нужно манипулировать).
- Свойство, к которому была применена привязка.
- Необязательный параметр, который можно установить в XAML с помощью свойства
ConverterParameter
. Этот параметр можно использовать для применения другого поведения в логике преобразователя. - Текущая культура.
Предыдущий пример кода показывает пример DateTime
упомянутый ранее. В методе Convert()
мы получаем исходное значение и после того, как мы преобразовали его в объект DateTime
, мы возвращаем строку с коротким форматированием.
В ConvertBack()
мы получаем строку, возвращаемую из ConvertBack()
управления, и преобразуем ее в объект DateTime
перед отправкой обратно в код.
Конвертеры обрабатываются как ресурсы — их нужно объявить и включить в выражение привязки с помощью ключевого слова StaticResource
.
1
2
3
4
|
<phone:PhoneApplicationPage.Resources>
<converters:DateTimeConverter x:Key=»DateConverter» />
</phone:PhoneApplicationPage.Resources>
<TextBlock Text=»{Binding Path=BirthDate, Converter={StaticResource DateConverter}}» />
|
Важно подчеркнуть, что конвертеры могут оказать негативное влияние на производительность, если вы используете их слишком интенсивно, поскольку операцию связывания необходимо повторять каждый раз при изменении данных. В этом случае лучше найти способ напрямую изменить исходные данные или добавить новое свойство в ваш класс с измененным значением.
управления
Windows Phone 8 SDK включает в себя множество встроенных элементов управления, которые можно использовать для определения пользовательского интерфейса приложения. Существует так много элементов управления, что практически невозможно проанализировать все из них в этой серии, поэтому мы подробнее рассмотрим только самые важные из них.
Элементы управления макетом
Некоторые элементы управления просто действуют как контейнеры для других элементов управления и определяют макет страницы. Давайте обсудим самые важные из них.
StackPanel
StackPanel
управления StackPanel
можно использовать для простого выравнивания вложенных элементов управления один под другим. Он может автоматически адаптироваться к размеру дочерних элементов управления.
1
2
3
4
|
<StackPanel>
<TextBlock Text=»First text» />
<TextBlock Text=»Second text» />
</StackPanel>
|
Вы также можете использовать StackPanel
управления StackPanel
для выравнивания элементов управления по горизонтали, один рядом с другим, установив для свойства Orientation
значение Horizontal
.
1
2
3
4
|
<StackPanel Orientation=»Horizontal»>
<TextBlock Text=»First text» />
<TextBlock Text=»Second text» />
</StackPanel>
|
сетка
Элемент управления Grid
можно использовать для создания макетов таблиц, которые заполняют весь размер родительского контейнера. Он поддерживает строки и столбцы, в которые вы можете поместить различные элементы управления. Следующий пример кода демонстрирует его использование:
01
02
03
04
05
06
07
08
09
10
11
|
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=»50″ />
<RowDefinition MaxHeight=»100″ />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=»200″ />
<ColumnDefinition Width=»*» />
</Grid.ColumnDefinitions>
<TextBlock Text=»1° row — 2° column» Grid.Row=»0″ Grid.Column=»1″ />
</Grid>
|
Вы определяете компоновку сетки с помощью свойств RowDefinitions
и ColumnDefinitions
. Вы можете добавить тег RowDefinition
для каждой строки, которую будет иметь таблица, а тег ColumnDefinition
можно использовать для установки количества столбцов. Для каждой строки и столбца вы можете установить ширину и высоту или просто опустить их, чтобы они автоматически адаптировались к вложенным элементам управления.
Чтобы определить положение элемента управления внутри сетки, мы будем использовать два прикрепленных свойства, которые являются специальными свойствами зависимостей, которые наследуются от Grid
управления Grid
и могут использоваться с каждым элементом управления. С Grid.Row
свойства Grid.Row
мы можем установить номер строки, а с помощью Grid.Column
мы можем установить номер столбца.
Предыдущий пример кода используется для отображения TextBlock
в ячейке, которая находится в первой строке второго столбца сетки, как вы можете видеть на следующем рисунке:
ScrollViewer
ScrollViewer
управления ScrollViewer
является контейнером, но он не определяет макет. Если вы хотите организовать вложенные элементы управления, вам все равно придется использовать другой контейнер, например, StackPanel
или Grid
. Целью этого элемента управления является создание макета, который больше, чем размер экрана. Таким образом, пользователи смогут прокрутить вниз, чтобы увидеть остальную часть пользовательского интерфейса.
Этот элемент управления полезен, например, когда вам нужно отобразить текст, который не соответствует размеру страницы.
1
2
3
4
5
|
<ScrollViewer>
<StackPanel>
<TextBlock TextWrapping=»Wrap» Text=»This can be long text» />
</StackPanel>
</ScrollViewer>
|
бордюр
Целью Border
контроля является отображение границы. Это полезно, потому что он может содержать дочерний элемент управления, который будет перенесен в границу.
В следующем примере показано, как обернуть изображение внутри красной рамки:
1
2
3
|
<Border BorderThickness=»5″ BorderBrush=»Red»>
<Image Source=»/Assets/windows-phone-8-logo.png»/>
</Border>
|
Существует несколько ключевых свойств элемента Border
. Первый — BorderThickness
, который определяет толщину границы. Вы можете указать одно значение, как мы делали в предыдущем примере. В этом случае к каждой стороне применяется одинаковая толщина. Вы также можете указать несколько значений, чтобы дать каждой границе разный размер, как в следующем примере:
1
2
3
|
<Border BorderThickness=»5, 10, 15, 20″ BorderBrush=»Red»>
<Image Source=»/Assets/windows-phone-8-logo.png»/>
</Border>
|
Второе важное свойство BorderBrush
, которое используется, чтобы установить кисть, которая применяется к границе. Он может использовать любую из доступных кистей XAML. По умолчанию он принимает SolidColorBrush
, так что вы можете просто указать цвет, который вы хотите применить.
Еще одно полезное свойство Padding
, которое можно использовать для указания расстояния между границей и дочерним элементом управления, как показано в следующем примере:
1
2
3
|
< Border BorderThickness = "5" BorderBrush = "Red" Padding = "10" > < Image Source = "/Assets/windows-phone-8-logo.png" /> </Border>
|
Управление выходом
Целью этих элементов управления является отображение чего-либо для пользователей, например текста, изображения и т. Д.
TextBlock
TextBlock
является одним из основных элементов управления XAML и используется для отображения текста на экране. Его самое важное свойство Text
, которое, конечно, содержит текст для отображения. У вас есть много свойств для выбора внешнего вида текста, таких как FontSize
, FontWeight
и FontStyle
, и вы можете автоматически переносить текст в несколько строк в случае, если текст слишком длинный, установив TextWrapping
свойство в true
.
1
|
< TextBlock Text = "This is long and bold text" TextWrapping = "Wrap" FontWeight = "Bold" /> |
Вы также можете применить другое форматирование к тексту, не используя несколько TextBlock
элементов управления, используя Run
тег, который можно использовать для разделения текста, как показано в следующем примере:
1
2
3
4
5
|
< TextBlock > < Run Text = "Standard text" /> < LineBreak /> < Run Text = "Bold test" FontWeight = "Bold" /> </TextBlock>
|
RichTextBlock
Элемент RichTextBlock
управления похож на TextBlock
, но он предлагает больше контроля над стилями форматирования, которые могут быть применены к тексту. Как и в HTML, вы можете определять абзацы, применять различные стили текста и многое другое.
1
2
3
4
5
6
7
8
9
|
< RichTextBox > < Paragraph > < Bold >This is a paragraph in bold</ Bold > </ Paragraph > < Paragraph > < Italic >This is a paragraph in italics</ Italic > < LineBreak /> </ Paragraph > </ RichTextBox > |
Образ
Элемент Image
управления может быть использован для отображения изображений. Вы можете установить Source
свойство с удаленным путем (URL-адрес изображения, опубликованный в Интернете) или локальным путем (файл, который является частью вашего проекта Visual Studio). Вы не можете назначить путь, который ссылается на изображение, хранящееся в локальном хранилище приложения. Позже в этой серии мы увидим, как справиться с этим ограничением.
1
|
|
Вы также можете управлять тем, как изображение будет адаптировано к размеру элемента управления, используя Stretch
свойство, которое может иметь следующие значения:
-
Uniform
: Значение по умолчанию. Размер изображения изменяется в соответствии с размером контейнера, сохраняя исходное соотношение сторон, чтобы изображение не выглядело искаженным. Если форматное соотношение контейнера отличается от изображения, изображение будет выглядеть меньше доступного пространства. -
Fill
: Изображение изменяется в соответствии с размером контейнера, игнорируя соотношение сторон. Он заполнит все доступное пространство, но если размер элемента управления не имеет такое же соотношение сторон, как у изображения, он будет выглядеть искаженным. -
UniformToFill
представляет собой смесь предыдущих значений. Если изображение имеет другое соотношение сторон, чем у контейнера, изображение обрезается, чтобы оно могло сохранить правильное соотношение сторон и в то же время заполнить все доступное пространство. -
None
: Изображение отображается в оригинальном размере.
Элементы управления вводом
Эти элементы управления используются для получения информации от пользователей.
Текстовое окно
TextBox
это еще один базовый элемент управления XAML, и это просто способ сбора текста от пользователей. Введенный текст будет сохранен в Text
свойстве элемента управления. Когда пользователи касаются элемента TextBox
управления, виртуальная клавиатура автоматически открывается. Как разработчик, вы можете контролировать тип клавиатуры, отображаемый в соответствии с типами данных, которые вы собираете.
Например, вы можете отобразить цифровую клавиатуру, если пользователям нужно только ввести число; или вы можете использовать клавиатуру электронной почты (которая обеспечивает легкий доступ к символам, таким как @), если вы собираете адрес электронной почты.
Вы можете контролировать тип клавиатуры с помощью InputScope
свойства. Список поддерживаемых значений очень длинный и его можно найти в документации MSDN . Некоторые из наиболее используемых:
-
Text
для общего ввода текста с поддержкой словаря. -
Number
для ввода общего числа. -
TelephoneNumber
для ввода конкретного телефонного номера (это та же клавиатура, которая отображается при составлении номера в собственном приложении Phone). -
EmailNameOrAddress
который добавляет быстрый доступ к символам, таким как @. -
Url
который добавляет быстрый доступ к общим доменам, таким как .com или .it (в зависимости от языка клавиатуры). -
Search
который предоставляет автоматические предложения.
1
|
< TextBox InputScope = "TelephoneNumber" /> |
Совет: если элемент управления TextBox используется для сбора общего текста, всегда не забывайте устанавливать для свойства InputScope значение Text. Таким образом, пользователи получат поддержку от инструментов автозаполнения и автокоррекции.
PasswordBox
PasswordBox
работает точно так же, как TextBox
элемент управления, за исключением того, что вставленные символы автоматически преобразуются в точки, так что люди рядом с пользователем не смогут прочитать текст. Как следует из названия элемента управления, он обычно используется для сбора паролей.
Тематические ресурсы
Одна из целей разработчика должна состоять в том, чтобы пользовательский интерфейс ее или его приложения был как можно более совместимым с рекомендациями операционной системы. Чтобы помочь в достижении этой цели, SDK предлагает множество готовых ресурсов, которые можно применять к элементам управления, чтобы получить тот же внешний вид и функции, что и собственные приложения. Эти стили обычно используются с такими элементами управления, как TextBox
, TextBlock
или RadioButton
, и они предоставляют стандартный набор визуальных функций (таких как размер шрифта, цвет, прозрачность и т. Д.), Которые согласуются с другими приложениями.
Еще одна веская причина использовать ресурсы тем — они знают о темах, заданных пользователями Например, вы можете использовать PhoneAccentBrush
стиль, если хотите придать элементу управления тот же цвет, что и цвет акцента телефона.
Многие ресурсы темы разделены на различные категории, такие как ресурсы кисти, ресурсы цвета, имена и стили шрифтов и текстовые ресурсы. Вы можете найти полный список доступных стилей в документации MSDN . Они просто применяются с использованием Style
свойства, предлагаемого каждым элементом управления, как показано в следующем примере:
1
|
< TextBlock Text = "App name" Style = "{StaticResource PhoneTextNormalStyle}" /> |
Взаимодействие с пользователями
В этой категории мы можем собрать все элементы управления , которые мы можем использовать для взаимодействия с пользователями, как Button
, CheckBox
, или RadioButton
.
Текст для отображения задается с помощью Content
свойства, как в следующем примере:
1
|
< Button Content = "Tap me" Tap = "OnClickMeClicked" /> |
Это Content
свойство также может быть сложным, так что вы можете добавить другие элементы управления XAML. В следующем примере мы видим, как вставить изображение внутри кнопки:
1
2
3
4
5
6
7
|
< Button Tap = "OnClickMeClicked" > < Button.Content > <StackPanel>
< Image Source = "/Assets/logo.png" Height = "200" /> </StackPanel>
</ Button.Content > </Button>
|
Эти элементы управления предлагают много способов взаимодействия с пользователями. Наиболее распространенные события Click
, Tap
и DoubleTap
.
Примечание. Нажатие и касание — это одно и то же событие — они оба запускаются, когда пользователи нажимают элемент управления. Tap был введен в Windows Phone 7.5 для большей совместимости с сенсорным интерфейсом, но во избежание взлома старых приложений событие Click по-прежнему поддерживается.
Элементы управления подписью Windows Phone
Большинство элементов управления, которые мы видели до сих пор, являются частью инфраструктуры XAML и доступны для любых других технологий на основе XAML, таких как приложения Silverlight, WPF и Windows Store.
Однако есть некоторые элементы управления, которые доступны только на платформе Windows Phone, поскольку они предназначены для мобильных устройств. Давайте посмотрим на них.
Панорама
Элемент Panorama
управления часто используется в приложениях Windows Phone, поскольку он обычно рассматривается как отправная точка. Элемент управления получает свое имя, потому что увеличенное изображение используется в качестве фона страницы. Пользователи могут проводить пальцем влево или вправо, чтобы увидеть другие доступные страницы. Поскольку изображение больше размера страницы, телефон применяет эффект параллакса, который визуально приятен для пользователей.
Другая главная особенность элемента Panorama
управления состоит в том, что пользователи могут получить краткий обзор следующей страницы. Текущая страница не занимает все доступное пространство, потому что на правой стороне отображается проблеск следующей страницы.
Элемент Panorama
управления обычно используется для предоставления обзора содержимого, которое доступно в приложении. Это отправная точка, а не контейнер данных. Например, нельзя использовать страницу панорамы для отображения всех новостей, опубликованных в блоге. Вместо этого лучше отображать только последние новости и предоставлять кнопку для перенаправления пользователей на другую страницу, где они смогут увидеть все из них.
С точки зрения разработчика, элемент Panorama
управления состоит из разных страниц: каждая из них является PanoramaItem
элементом управления, который содержит макет страницы.
Panorama
Может иметь родовое название, как название приложения (которое присвоенная Title
собственность), в то время как каждая страница может иметь свой собственный специфический заголовок (который назначен на Header
имущество).
01
02
03
04
05
06
07
08
09
10
11
12
|
< phone:Panorama Title = "Panorama" > < phone:PanoramaItem Header = "First page" > <StackPanel>
< TextBlock Text = "Page 1" /> </StackPanel>
</phone:PanoramaItem>
< phone:PanoramaItem Header = "Second page" > <StackPanel>
< TextBlock Text = "Page 2" /> </StackPanel>
</phone:PanoramaItem>
</phone:Panorama>
|
Примечание. Элемент управления Panorama (например, элемент управления Pivot) не доступен по умолчанию на странице. Вам придется объявить следующее пространство имен:
1
|
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" |
стержень
Элемент Pivot
управления, с технической точки зрения и с точки зрения взаимодействия с пользователем, работает аналогично элементу Panorama
управления: пользователи могут проводить пальцем по экрану влево или вправо для просмотра других страниц. Разница, с точки зрения пользователей, заключается в том, что представление будет соответствовать размеру экрана. Пользователи могут видеть, какая страница следующая, потому что ее заголовок отображается рядом с заголовком текущей страницы серым цветом.
Тем не менее, Pivot
элемент управления используется в целях, не разделяемых элементом Panorama
управления:
- Для отображения одного вида информации применяется к различным контекстам. Предыдущая цифра является хорошим примером. Информация на каждой странице одинакова (прогноз погоды), но упоминается в разных контекстах (городах).
- Для отображения различных видов информации, которые относятся к одному и тому же контексту. Хорошей тому пример является страница с информацией о контактах в People Hub на Windows Phone — у вас много информации (контакт, обновления в социальных сетях, разговоры и т. Д.), Но все это относится к одному контексту (контакту) ,
Как и предполагалось ранее, XAML для элемента Pivot
управления работает так же, как XAML для элемента Panorama
управления. Вызывается основной элемент управления Pivot
, а вызываются вложенные элементы управления, представляющие страницы PivotItem
.
01
02
03
04
05
06
07
08
09
10
11
12
|
< phone:Pivot Title = "Pivot" > < phone:PivotItem Header = "First page" > <StackPanel>
< TextBlock Text = "Page 1" /> </StackPanel>
</phone:PivotItem>
< phone:PivotItem Header = "Second page" > <StackPanel>
< TextBlock Text = "Page 2" /> </StackPanel>
</phone:PivotItem>
</phone:Pivot>
|
Панель приложений
Элемент ApplicationBar
управления расположен в нижней части страницы и используется для быстрого доступа к функциям, которые связаны с текущим представлением.
Вы можете добавить два типа элементов на панель приложения:
- Иконки всегда отображаются (если они
ApplicationBar
не свернуты), и одновременно может отображаться до четырех. - Пункты меню — это просто текстовые элементы, которые отображаются только при открытой панели приложения. Там нет ограничений на количество предметов, которые могут быть включены.
ApplicationBar
Не ведет себя , как и другие элементы управления XAML. Он не является частью страницы — на самом деле он объявлен вне основного Grid
, называемого LayoutRoot
— и не наследуется от FrameworkElement
класса, как любой другой элемент управления. Самым большим недостатком этого является то, что элемент управления не поддерживает привязку; вам придется полагаться на сторонние библиотеки, например на реализацию, доступную в Cimbalino Toolkit для Windows Phone .
Вот ApplicationBar
образец:
1
2
3
4
5
6
7
8
|
< phone:PhoneApplicationPage.ApplicationBar > < shell:ApplicationBar IsVisible = "True" IsMenuEnabled = "True" > < shell:ApplicationBarIconButton IconUri = "/Assets/Add.png" Text = "Add" Click = "ApplicationBarIconButton_Click" /> < shell:ApplicationBar.MenuItems > < shell:ApplicationBarMenuItem Text = "update" Click = "ApplicationBarMenuItem_Click" /> </ shell:ApplicationBar.MenuItems > </ shell:ApplicationBar > </ phone:PhoneApplicationPage.ApplicationBar > |
ApplicationBar
это свойство PhoneApplicationPage
класса, которое содержит реальное ApplicationBar
определение. Это не часть стандартных пространств имен XAML, но это часть следующего пространства имен, которое уже должно быть объявлено на каждой стандартной странице Windows Phone:
1
|
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" |
Иконки кнопок объявляются прямо внутри ApplicationBar
тега. Базовый класс есть ApplicationBarIconButton
, и наиболее важными свойствами являются Text
(описание значка) и IconUri
(путь к изображению, используемому в качестве значка), в то время как Click
это обработчик событий, который вызывается, когда пользователь нажимает кнопку.
Вместо этого пункты меню сгруппированы внутри свойства ApplicationBar
вызываемого элемента управления MenuItems
. Вы можете добавить столько ApplicationBarMenuItem
элементов управления, сколько хотите. Они ведут себя как значки кнопок, за исключением того, что, поскольку они являются просто текстом, IconUri
свойство отсутствует.
Другим важным ограничением элемента ApplicationBar
управления является то, что мы не можем присвоить x:Name
свойство элементу управления ApplicationBarIconButton
или ApplicationBarMenuItem
. Это означает, что если нам нужно изменить значение свойства в коде, мы не можем просто использовать нотацию ControlName.PropertyName
.
Обходной путь — использовать код для прямого доступа к коллекциям, которые содержат кнопки и пункты меню, доступные из-за ApplicationBar
объекта. Они вызываются Buttons
и MenuItems
, как вы можете видеть в следующем примере кода:
1
2
3
4
|
ApplicationBarIconButton iconButton = this .ApplicationBar.Buttons[0] as ApplicationBarIconButton; iconButton.Text = "New text" ; ApplicationBarMenuItem menuItem = this .ApplicationBar.MenuItems[0] as ApplicationBarMenuItem; menuItem.Text = "New text" ; |
Цель этого примера — получить доступ к первой кнопке со значком и первому элементу меню внутри ApplicationBar
и изменить значение Text
свойства.
В конце концов, есть два других способа настройки ApplicationBar
. Первое — минимизировать это. Таким образом, будут отображены только три точки на правом поле; значки не будут видны Чтобы достичь этого, вы должны установить Mode
свойство Minimized.
Другой способ — изменить непрозрачность. Вы можете установить Opacity
свойство со значением от 0 (прозрачный) до 1 (непрозрачный). Самым большим отличием является то, что при ApplicationBar
прозрачности содержимое страницы будет идти ниже полосы и умещаться на весь размер экрана; когда панель непрозрачна, содержимое не будет занимать все доступное пространство экрана, так как нижняя часть страницы будет зарезервирована для ApplicationBar
.
Отображение коллекций данных с помощью LongListSelector
Одним из наиболее распространенных требований в приложении является отображение набора элементов, которые можно извлечь из удаленной службы или локальной базы данных. Windows Phone SDK включает с самого начала некоторые элементы управления для этой цели, такие как ItemsControl
и ListBox
. В Windows Phone 8 Microsoft представила новый и более мощный элемент управления, который ранее был доступен как часть Windows Phone Toolkit (более подробно об этом наборе вы узнаете позже в этой статье). Этот элемент управления называется LongListSelector
и имеет много преимуществ по сравнению с другими аналогичными элементами управления:
- лучшая производительность
- поддержка виртуализации, чтобы избежать загрузки всех данных одновременно, вместо этого загружая данные только тогда, когда это необходимо
- поддержка группы, чтобы превратить список в a
jump list
, чтобы данные группировались по категориям и пользователи могли легко переходить от одного к другому (например, в People Hub контакты сгруппированы по первой букве)
Создание плоского списка
Элемент LongListSelector
управления можно использовать как обычный ListBox
для отображения плоского списка элементов без группировки. В этом случае вам просто нужно установить IsGroupingEnabled
свойство в false
. За исключением этой модификации, вы сможете использовать LongListSelector
как стандарт ItemsControl
. Вы определите ItemTemplate
свойство с помощью, DataTemplate
чтобы определить макет элемента, и назначите коллекцию, которую вы хотите отобразить, ItemsSource
свойству.
1
2
3
|
< phone:LongListSelector x:Name = "List" IsGroupingEnabled = "False" ItemTemplate = "{StaticResource PeopleItemTemplate}" /> |
Создание списка, сгруппированного по буквам
Создание списка, сгруппированного по первой букве элементов, немного сложнее, так как мы должны изменить наш источник данных. Это больше не будет простой набор данных. Кроме того, если мы хотим, чтобы взаимодействие с пользователем было совместимо с другими приложениями, нам необходимо создать список переходов со всеми буквами алфавита. Группы, в которых нет участников, будут отключены, чтобы пользователи не могли их коснуться.
Чтобы достичь этого результата, Microsoft предлагает класс под названием AlphaKeyGroup<T>
, который представляет букву алфавита и все элементы, которые начинаются с него. Однако этот класс не является частью Windows Phone SDK и должен быть добавлен в проект вручную, щелкнув правой кнопкой мыши проект в обозревателе решений в Visual Studio и выбрав Добавить новый класс . В следующем примере кода приведена полная реализация.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
public class AlphaKeyGroup<T> : List<T> {
/// <summary>
/// The delegate that is used to get the key information. /// </summary>
/// <param name="item">An object of type T.</param> /// <returns>The key value to use for this object.</returns> public delegate string GetKeyDelegate(T item); /// <summary>
/// The key of this group. /// </summary>
private set;
/// <summary>
/// Public constructor. /// </summary>
/// <param name="key">The key for this group.</param> public AlphaKeyGroup( string key) {
Key = key; }
/// <summary>
/// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping. /// </summary>
/// <param name="slg">The </param> /// <returns>The items source for a LongListSelector.</returns> private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg) {
List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>(); foreach ( string key in slg.GroupDisplayNames) {
list.Add( new AlphaKeyGroup<T>(key)); }
return list;
}
/// <summary>
/// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping. /// </summary>
/// <param name="items">The items to place in the groups.</param> /// <param name="ci">The CultureInfo to group and sort by.</param> /// <param name="getKey">A delegate to get the key from an item.</param> /// <param name="sort">Will sort the data if true.</param> /// <returns>An items source for a LongListSelector.</returns> public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort) {
SortedLocaleGrouping slg = new SortedLocaleGrouping(ci); List<AlphaKeyGroup<T>> list = CreateGroups(slg); foreach (T item in items) {
int index = 0; if (slg.SupportsPhonetics) {
//Checks whether your database has the string yomi as an item. //If it does not, then generate Yomi or ask users for this item. //index = slg.GetGroupIndex(getKey(Yomiof(item))); }
else
{
index = slg.GetGroupIndex(getKey(item)); }
if (index >= 0 && index < list.Count) {
list[index].Add(item); }
}
if (sort) {
foreach (AlphaKeyGroup<T> group in list) {
group .Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); }); }
}
return list;
}
}
|
Основными особенностями этого класса являются:
- Он наследуется от
List<T>
, поэтому он представляет список элементов. - У него есть свойство под названием
Key
, которое является ключом, идентифицирующим группу (буква алфавита). - Он использует специальный тип коллекции
SortedLocaleGroup
, который может управлять культурными различиями между языками. - Он предлагает метод под названием
CreateGroups()
, который мы будем использовать для группировки наших данных.
Чтобы лучше объяснить, как использовать AlphaKeyGroup<T>
класс, давайте приведем реальный пример. Давайте определим группу людей, которых мы хотим сгруппировать, по первым буквам их имен, аналогично тому, как это делает People Hub. Первый шаг — создать класс, представляющий одного человека:
1
2
3
4
5
6
|
public class Person
{
public string Name { get;
public string Surname { get;
set;
}
|
Затем, когда приложение запускается, мы заполняем список набором поддельных данных, как показано в следующем примере:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
void LongListSelectorAlphabetic_Loaded( object sender, RoutedEventArgs e) {
List<Person> people = new List<Person> {
new Person {
Name = "John" , Surname = "Doe" , City = "Como" },
new Person {
Name = "Mark" , Surname = "Whales" , City = "Milan" },
new Person {
Name = "Ricky" , Surname = "Pierce" , City = "New York" }
};
}
|
Теперь пришло время использовать AlphaGroupKey<T>
класс для преобразования этого плоского списка в сгруппированный список, вызвав CreateGroups()
метод.
1
2
3
|
List<AlphaKeyGroup<Person>> list = AlphaKeyGroup<Person>.CreateGroups(people, Thread.CurrentThread.CurrentUICulture, p => p.Name, true ); |
Метод требует четырех параметров:
- Коллекция, которую мы хотим сгруппировать: в примере это коллекция
Person
объектов, которые мы создали. - Культура, используемая для создания букв алфавита. Стандартная практика заключается в использовании значения
Thread.CurrentThread.CurrentUICulture
свойства, которое является основным языком, установленным пользователем для телефона. - Свойство объекта, которое будет использоваться для группировки: это указывается с помощью лямбда-выражения. В примере список будет сгруппирован по первой букве имени.
- Последний параметр,
Boolean
тип, используется для определения того, применять ли упорядочение: если установлено значениеtrue
, коллекция будет упорядочена в алфавитном порядке.
В ответ мы получаем набор AlphaKeyGroup<T>
объектов, по одному на каждую букву алфавита. Это коллекция, которую нам нужно присвоить ItemsSource
свойству LongListSelectorControl
.
1
2
3
4
5
|
List<AlphaKeyGroup<Person>> list = AlphaKeyGroup<Person>.CreateGroups(people, Thread.CurrentThread.CurrentUICulture, p => p.Name, true ); People.ItemsSource = list; |
Однако этого кода недостаточно — нам также необходимо предоставить дополнительные шаблоны в XAML, которые используются для определения макета списка переходов.
Вызывается первое свойство, которое нужно установить GroupHeaderTemplate
, и оно представляет заголовок, который отображается в списке перед каждой группой. В случае буквенного списка это само письмо. В следующем коде XAML показан образец шаблона, который воссоздает внешний вид родных приложений:
1
2
3
4
5
6
7
8
9
|
< DataTemplate x:Key = "PeopleGroupHeaderTemplate" > < Border Background = "Transparent" Padding = "5" > < Border Background = "{StaticResource PhoneAccentBrush}" BorderBrush = "{StaticResource PhoneAccentBrush}" BorderThickness = "2" Width = "62" Height = "62" Margin = "0,0,18,0" HorizontalAlignment = "Left" > < TextBlock Text = "{Binding Key}" Foreground = "{StaticResource PhoneForegroundBrush}" FontSize = "48" Padding = "6" FontFamily = "{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment = "Left" VerticalAlignment = "Center" /> </Border>
</Border>
</DataTemplate>
|
При такой раскладке письмо помещается в квадрат с цветом фона, совпадающим с цветом акцента телефона. Обратите внимание на две важные вещи:
- Некоторые свойства элемента
Border
управления используютPhoneAccentBrush
ресурс. Это один из ранее описанных ресурсов темы, который определяет цвет акцента телефона. Text
СвойствоTextBlock
управления связан сKey
свойствомAlphaGroupKey<T>
класса. Таким образом, мы можем отобразить букву группы внутри квадрата.
Второе свойство, которое нужно определить, вызывается JumpListStyle
и, в отличие от предыдущего свойства, это не шаблон, а стиль. Его цель — определить внешний вид списка переходов, который является видом, который отображается, когда пользователи нажимают на букву. Он отображает все буквы алфавита, так что пользователи могут нажать одну из них и быстро перейти к этой группе.
Вот примерное определение, которое, опять же, воссоздает внешний вид нативных приложений — все буквы алфавита отображаются рядом в нескольких строках.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
< phone:JumpListItemBackgroundConverter x:Key = "BackgroundConverter" /> < phone:JumpListItemForegroundConverter x:Key = "ForegroundConverter" /> < Style x:Key = "PeopleJumpListStyle" TargetType = "phone:LongListSelector" > < Setter Property = "GridCellSize" Value = "113,113" /> < Setter Property = "LayoutMode" Value = "Grid" /> < Setter Property = "ItemTemplate" > < Setter.Value > <DataTemplate>
< Border Background = "{Binding Converter={StaticResource BackgroundConverter}}" Width = "113" Height = "113" Margin = "6" > < TextBlock Text = "{Binding Key}" FontFamily = "{StaticResource PhoneFontFamilySemiBold}" FontSize = "48" Padding = "6" Foreground = "{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment = "Center" /> </Border>
</DataTemplate>
</ Setter.Value > </ Setter > </ Style > |
Этот стиль использует два преобразователя , которые являются частью Windows Phone Toolkit называется JumpListItemBackgroundConverter
и JumpListItemForegroundConverter
. Как видно из того, ItemTemplate
что применяется к элементу управления, эти конвертеры используются для определения цвета текста и цвета Border
фона. Их цель — управлять пустыми группами. Если коллекция содержит один или несколько элементов, она будет отображаться белым цветом с акцентом на телефоне в качестве фона. Если вместо этого буква связана с группой без элементов, текст и фон будут серыми. Таким образом, пользователи сразу видят, что группа отключена, и нажатие на нее не даст никакого эффекта.
В конце не забывайте, что как и для любого другого элемента управления, основанного на ItemsControl
классе, вам нужно установить ItemTemplate
свойство с помощью a, DataTemplate
чтобы определить, как будет выглядеть отдельный элемент. В следующем примере показана базовая реализация, где имя и фамилия отображаются один под другим:
1
2
3
4
5
6
|
< DataTemplate x:Key = "PeopleItemTemplate" > <StackPanel>
< TextBlock Text = "{Binding Name}" /> < TextBlock Text = "{Binding Surname}" /> </StackPanel>
</DataTemplate>
|
Собрав все необходимые стили и шаблоны, вы можете применить их к LongListSelector
управления, как показано в следующем примере:
1
2
3
4
5
6
7
|
< phone:LongListSelector x:Name = "People" GroupHeaderTemplate = "{StaticResource PeopleGroupHeaderTemplate}" ItemTemplate = "{StaticResource PeopleItemTemplate}" JumpListStyle = "{StaticResource PeopleJumpListStyle}" IsGroupingEnabled = "True" HideEmptyGroups = "True" /> |
Обратите внимание на HideEmptyGroups
свойство, которое можно использовать для скрытия всех групп в списке, которые не содержат никаких элементов.
Создание списка, сгруппированного по категориям
В некоторых случаях нам может потребоваться сгруппировать элементы по настраиваемому полю вместо первой буквы. Давайте посмотрим на другой пример. Мы хотим сгруппировать Person
объекты по City
полю; нам нужен класс для заменыAlphaKeyGroup<T>
, так как он не подходит для нашего сценария.
Давайте представим Group<T>
класс, который намного проще:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public class Group<T> : List<T> {
public Group( string name, IEnumerable<T> items) : base (items) {
this .Key = name; }
public string Key {
get;
set;
}
}
|
Под капотом этот класс ведет себя как AlphaKeyGroup<T>
. Он наследуется от List<T>
, поэтому представляет коллекцию элементов и определяет группу, которая идентифицируется ключом (который будет именем категории).
01
02
03
04
05
06
07
08
09
10
|
private List<Group<T>> GetItemGroups<T>(IEnumerable<T> itemList, Func<T, string > getKeyFunc) {
IEnumerable<Group<T>> groupList = from item in itemList group item by getKeyFunc(item) into g orderby g.Key select new Group<T>(g.Key, g); return groupList.ToList(); }
|
Предыдущий метод принимает в качестве входных параметров:
- квартира коллекции в группу.
- функция (выраженная лямбда-выражением) для установки свойства объекта, которое мы хотим использовать для группировки
В следующем примере показан код, который мы можем использовать для группировки коллекции Person
объектов по City
свойству:
1
2
|
List<Group<Person>> groups = GetItemGroups(people, x => x.City); PeopleByCity.ItemsSource = groups; |
Результат, возвращаемый GetItemGroups()
методом, может быть напрямую присвоен ItemsSource
свойству элемента LongListSelector
управления.
Как и в сценарии с группировкой по алфавиту, нам все еще нужно определить макет заголовков группы и список переходов. Мы можем повторно использовать ресурсы, которые мы ранее определили, но, если мы хотим добиться лучшего результата, мы можем адаптировать их так, чтобы фоновый прямоугольник заполнил размер имени категории, как показано в следующем примере кода:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
< phone:JumpListItemBackgroundConverter x:Key = "BackgroundConverter" /> < phone:JumpListItemForegroundConverter x:Key = "ForegroundConverter" /> < DataTemplate x:Key = "PeopleCityGroupHeaderTemplate" > < Border Background = "Transparent" Padding = "5" > < Border Background = "{StaticResource PhoneAccentBrush}" BorderBrush = "{StaticResource PhoneAccentBrush}" BorderThickness = "2" Height = "62" Margin = "0,0,18,0" HorizontalAlignment = "Left" > < TextBlock Text = "{Binding Key}" Foreground = "{StaticResource PhoneForegroundBrush}" FontSize = "48" Padding = "6" FontFamily = "{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment = "Left" VerticalAlignment = "Center" /> </Border>
</Border>
</DataTemplate>
< Style x:Key = "PeopleCityJumpListStyle" TargetType = "phone:LongListSelector" > < Setter Property = "GridCellSize" Value = "113,113" /> < Setter Property = "LayoutMode" Value = "List" /> < Setter Property = "ItemTemplate" > < Setter.Value > <DataTemplate>
< Border Background = "{Binding Converter={StaticResource BackgroundConverter}}" Height = "113" Margin = "6" > < TextBlock Text = "{Binding Key}" FontFamily = "{StaticResource PhoneFontFamilySemiBold}" FontSize = "48" Padding = "6" Foreground = "{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment = "Center" /> </Border>
</DataTemplate>
</ Setter.Value > </ Setter > </ Style > |
На следующем рисунке показан результат примера кода.
Не забудьте собрать LongListSelector
элемент управления, добавив все стили и шаблоны, которые вы только что создали, как показано в следующем примере:
1
2
3
4
5
6
|
< phone:LongListSelector x:Name = "PeopleByCity" ItemTemplate = "{StaticResource PeopleItemTemplate}" GroupHeaderTemplate = "{StaticResource PeopleCityGroupHeaderTemplate}" JumpListStyle = "{StaticResource PeopleCityJumpListStyle}" IsGroupingEnabled = "True" /> |
Взаимодействие со списком
При взаимодействии с элементом LongListSelector
управления (или любым другим элементом управления, унаследованным от ItemsControl
класса) необходимо учитывать две ключевые концепции :
SelectionChanged
событие, которое срабатывает каждый раз , когда пользователь нажимает один из элементов в спискеSelectedItem
свойство, которое хранит элементы , которые были выбраны пользователем
С помощью комбинации этих двух элементов вы сможете определить, когда и какой элемент был выбран пользователем, и правильно ответить. Например, вы можете перенаправить пользователя на страницу, где он или она может видеть детали выбранного элемента.
1
2
3
4
5
|
< phone:LongListSelector x:Name = "People" GroupHeaderTemplate = "{StaticResource PeopleGroupHeaderTemplate}" ItemTemplate = "{StaticResource PeopleItemTemplate}" SelectionChanged = "LongListSelectorAlphabetic_Loaded" /> |
В предыдущем примере показан элемент LongListSelector
управления, который был подписан на SelectionChanged
событие. В следующем примере вместо этого показан код обработчика события:
1
2
3
4
5
6
|
private void People_OnSelectionChanged( object sender, SelectionChangedEventArgs e) {
Person selectedPerson = People.SelectedItem as Person; string uri = string .Format( "/DetailPage.xaml?Id={0}" , selectedPerson.Id); NavigationService.Navigate( new Uri(uri, UriKind.Relative)); }
|
В предыдущем примере показан элемент LongListSelector
управления, который был подписан на SelectionChanged
событие. В следующем примере вместо этого показан код обработчика события:
1
2
3
4
5
6
|
private void People_OnSelectionChanged( object sender, SelectionChangedEventArgs e) {
Person selectedPerson = People.SelectedItem as Person; string uri = string .Format( "/DetailPage.xaml?Id={0}" , selectedPerson.Id); NavigationService.Navigate( new Uri(uri, UriKind.Relative)); }
|
Благодаря этому SelectedItem
свойству мы извлекаем выбранный Person
объект и перенаправляем пользователя на другую страницу с именемDetailPage.xaml
для отображения сведений о выбранном человеке. Мы подробно рассмотрим навигацию в следующей статье.
Набор инструментов для Windows Phone
В этой статье мы рассмотрели только основные элементы управления, но вы заметите, что в SDK отсутствует множество элементов управления, которые используются в других приложениях. Большинство из них доступны в библиотеке Windows Phone Toolkit, которая доступна в CodePlex и NuGet . Он поддерживается непосредственно Microsoft и является способом сохранить отдельный, более быстрый процесс разработки, чем тот, который необходим для выпуска новой версии SDK.
Вот краткий список наиболее важных доступных элементов управления:
-
ToggleSwitch
: Особенно полезно для страниц настроек, так как это переключатель, который можно использовать для определения логического значения (вкл / выкл). -
ContextMenu
: Меню, которое может отображаться, когда пользователи нажимают и удерживают элемент. -
DatePicker
иTimePicker
: Используется для выбора даты или времени соответственно. -
WrapPanel
: Специальный контейнер, который может выровнять вложенные элементы управления рядом друг с другом и автоматически переносить на новую строку, если не осталось места. -
AutoCompleteBox
: Специальное предложение,TextBox
которое может подсказывать пользователю подсказки на основе текста, набираемого пользователем. -
ListPicker
: Используется для отображения списка элементов. Это особенно полезно, когда вы просите пользователей выбирать между различными значениями. -
ExpanderView
: Используется для создания элементов, которые можно развернуть, используя древовидную структуру для отображения других элементов. Хорошим примером этого элемента управления является приложение Почта; он используется для отображения разговоров. -
MultiSelectList
: Аналогично aListBox
, но автоматически ставит флажки рядом с каждым элементом, позволяя пользователям выбирать несколько элементов. -
PhoneTextBox
: СпециальныйTextBox
элемент управления со множеством встроенных функций, таких как поддержка значков действий, заполнителей, счетчика символов и т. Д. -
HubTile
: Может использоваться для воссоздания начального экрана, предлагаемого Live Tiles, внутри приложения. -
CustomMessageBox
: СпециальноеMessageBox
предложение, которое предлагает гораздо больше опций, чем стандартный, например, настройка кнопок, поддержка пользовательских шаблонов и т. Д. -
Rating
Предоставляет пользователям возможность оценивать что-либо внутри приложения. Пользовательский опыт похож на тот, который предлагает Магазин, где пользователи могут голосовать за приложение. -
SpeechTextBox
Еще одна особенность,TextBox
которая поддерживает распознавание голоса, так что пользователи могут диктовать текст вместо его ввода.
Windows Phone Toolkit также включает в себя замену фрейма Windows Phone (класс, который управляет представлениями и навигацией) со встроенной поддержкой анимации, так что вы можете легко добавлять эффекты перехода, когда пользователи переходят с одной страницы приложения на другую. Давайте углубимся в эту тему.
Переходы страницы
В этой статье мы узнали, как анимировать объекты, размещенные на странице. Зачастую одним из самых простых способов улучшить внешний вид нашего приложения является добавление анимации при переходе с одной страницы на другую. Набор инструментов для Windows Phone играет важную роль в достижении этого результата, поскольку стандартный фрейм приложения, предоставляемый SDK, который управляет всеми страницами нашего приложения, не поддерживает переходы. Вместо этого инструментарий предлагает определенный класс кадров, который называется TransitionFrame
, который можно использовать для замены исходного класса кадров, который вызывается PhoneApplicationFrame
.
Первым шагом является замена оригинальной рамы. Вы можете сделать это в App.xaml.cs
файле, который содержит скрытую область под названием « Инициализация приложения телефона» . Если вы развернете его, вы найдете метод, InitializePhoneApplication()
который, помимо прочего, инициализирует фрейм приложения следующим кодом:
1
|
RootFrame = new PhoneApplicationFrame(); |
Замена оригинальной рамы очень проста. После установки Windows Phone Toolkit вы можете изменить инициализацию RootFrame
объекта с помощью TransitionFrame
класса, который является частью Microsoft.Phone.Controls
пространства имен, как показано в следующем примере:
1
|
RootFrame = new TransitionFrame(); |
Теперь вы готовы установить, какую анимацию вы хотите использовать на своих страницах, в соответствии с типом навигации. Давайте начнем с рассмотрения следующего примера кода, который необходимо добавить на каждую страницу, которую вы хотите анимировать с помощью перехода. Код должен быть размещен под главным PhoneApplicationPage
узлом, прежде чем будет определен макет страницы:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
< toolkit:TransitionService.NavigationInTransition > < toolkit:NavigationInTransition > < toolkit:NavigationInTransition.Backward > < toolkit:TurnstileTransition Mode = "BackwardIn" /> </ toolkit:NavigationInTransition.Backward > < toolkit:NavigationInTransition.Forward > < toolkit:TurnstileTransition Mode = "ForwardIn" /> </ toolkit:NavigationInTransition.Forward > </ toolkit:NavigationInTransition > </ toolkit:TransitionService.NavigationInTransition > < toolkit:TransitionService.NavigationOutTransition > < toolkit:NavigationOutTransition > < toolkit:NavigationOutTransition.Backward > < toolkit:TurnstileTransition Mode = "BackwardOut" /> </ toolkit:NavigationOutTransition.Backward > < toolkit:NavigationOutTransition.Forward > < toolkit:TurnstileTransition Mode = "ForwardOut" /> </ toolkit:NavigationOutTransition.Forward > </ toolkit:NavigationOutTransition > </ toolkit:TransitionService.NavigationOutTransition > |
Переходы добавляются с помощью TransitionService
, который является частью Windows Phone Toolkit (убедитесь, что xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
пространство имен добавлено на вашу страницу).
Поддерживаются два типа анимации, указанные с помощью NavigationInTransition
свойства:
-
In
анимации, которые применяются, когда пользователи переходят на текущую страницу -
Out
анимации, которые применяются, когда пользователи уходят с текущей страницы
Для каждого типа перехода у вас также есть возможность указать два дополнительных условия:
Backward
Свойство используется для указания перехода к использованию , когда пользователи достигают страницы после нажатия кнопки Назад.Forward
Свойство используется для указания перехода использовать , когда пользователи достигают страницы с помощью обычной навигации потока.
Наконец, вы можете указать, какой переход вы хотите использовать для каждого сценария. Инструментарий предлагает список предопределенных анимаций, таких как RotateTransition
применение эффекта вращения, TurnstileTransition
имитация просмотра книги или SlideTransition
применение эффекта слайда. Каждый переход предлагает Mode
свойство, которое можно использовать для настройки применяемого эффекта. В предыдущем примере показан TurnstileTransition
эффект, применяемый во время каждой навигации, с различным эффектом в зависимости от типа навигации (назад или вперед).
Настроить турникет переход
Каркас анимации можно использовать не только для применения перехода ко всей странице, но и для каждого элемента управления на странице. Этот сценарий поддерживается TurnstileFeatherTransition
элементом управления, который применяет эффект турникета к элементам управления на странице. Вы можете решить, какой порядок будет использоваться для анимации, и ввести элементы управления на странице со FeatheringIndex
свойством.
Первым шагом является добавление TransitionService
на свою страницу и определение набора TurnstileFeatherTransition
анимаций, как в следующем примере:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
< toolkit:TransitionService.NavigationInTransition > < toolkit:NavigationInTransition > < toolkit:NavigationInTransition.Backward > < toolkit:TurnstileFeatherTransition Mode = "BackwardIn" /> </ toolkit:NavigationInTransition.Backward > < toolkit:NavigationInTransition.Forward > < toolkit:TurnstileFeatherTransition Mode = "ForwardIn" /> </ toolkit:NavigationInTransition.Forward > </ toolkit:NavigationInTransition > </ toolkit:TransitionService.NavigationInTransition > < toolkit:TransitionService.NavigationOutTransition > < toolkit:NavigationOutTransition > < toolkit:NavigationOutTransition.Backward > < toolkit:TurnstileFeatherTransition Mode = "BackwardOut" /> </ toolkit:NavigationOutTransition.Backward > < toolkit:NavigationOutTransition.Forward > < toolkit:TurnstileFeatherTransition Mode = "ForwardOut" /> </ toolkit:NavigationOutTransition.Forward > </ toolkit:NavigationOutTransition > </ toolkit:TransitionService.NavigationOutTransition > |
Затем вы можете применить TurnstileFeatherTransition.FeatheringIndex
свойство к любому элементу управления на странице и указать порядок, в котором они будут отображаться, начиная с 0, чтобы задать первый элемент управления, который будет вводиться на странице.
1
2
3
4
5
6
7
8
|
<StackPanel>
< TextBlock Text = "First Element" toolkit:TurnstileFeatherEffect.FeatheringIndex = "0" /> < TextBlock Text = "Second Element" toolkit:TurnstileFeatherEffect.FeatheringIndex = "1" /> < TextBlock Text = "Third Element" toolkit:TurnstileFeatherEffect.FeatheringIndex = "2" /> </StackPanel>
|
В предыдущем примере TextBlock
на странице появятся три элемента управления, начиная с первого (значение которого FeatheringIndex
равно 0) и заканчивая последним (значение которого FeatheringIndex
равно 2).
Вывод
Это был долгий путь, и мы только поцарапали поверхность; для охвата всех функций XAML потребуется целая книга. В этой статье мы рассмотрели некоторые ключевые концепции, используемые при разработке Windows Phone:
- Мы ввели основные концепции XAML, такие как свойства, события, пространства имен и ресурсы.
- Мы узнали, как работает привязка данных. Это одна из самых мощных функций XAML, и очень важно понимать ее как продуктивную.
- Мы видели некоторые из основных элементов управления, которые включены в SDK, и как мы можем использовать их для определения пользовательского интерфейса нашего приложения.
- Мы обсудили некоторые элементы управления , которые являются специфическими для опыта Windows Phone, как
Panorama
,Pivot
иApplicationBar
управление.
Это руководство представляет собой главу из Windows Phone 8 Succinctly , бесплатной электронной книги от команды Syncfusion.