Створення власних елементів управління Windows Runtime

У цьому розділі мова піде про створення власних елементів на основі існуючих У бібліотеці Windows Runtime міститься безліч нових елементів з певним поданням Але, завдяки можливостям XAML і дизайну цих елементів, на їх основі можна отримати щось нестандартне

У попередніх розділах ми використовували такі стилі, якAppBarButtonStyle і BackButtonStyle, Щоб задати для простого елемента Button характерні властивості (кнопка панелі програми і кнопка Back) При цьому елемент Button не просто міняв колір і розміри, але і брав абсолютно нову форму, а також підключав додаткову анімацію для подій, повязаних із взаємодією з користувачем

Все це стало можливим завдяки поділу подання та логіки елемента Так, логіка визначає події, задає стану та групи станів елемента, його обовязкові частини У поданні розробник може повністю описати зовнішній вигляд елемента, використовуючи будь-які графічні примітиви, а також більш складні елементи (наприклад, контейнери)

Розглянемо стандартний стиль для кнопки на панелі програми (AppBarButtonStyle) Перше, що відбувається всередині цього коду, це установка стандартних властивостей кнопки:

&ltSetter Property=&quotForeground&quot

Value=&quot{StaticResource AppBarItemForegroundBrush}&quot/&gt

&ltSetter Property=&quotVerticalAlignment&quot Value=&quotStretch&quot/&gt

&ltSetter Property=&quotFontFamily&quot Value=&quotSegoe UI Symbol&quot/&gt

&ltSetter Property=&quotFontWeight&quot Value=&quotNormal&quot/&gt

Тут немає нічого цікавого А от на що потрібно звернути увагу, так це на установку спеціального властивостіTemplate Саме за допомогою цієї властивості і задається зовнішній вигляд елемента керування «кнопка» При цьому шаблон елемента досить обємний, тому для його створення використовується елемент-контейнерControlTemplate, Який може входити до складу стилю або бути самостійним елементом в ресурсах Вашого застосування Якщо ControlTemplate  задається як окремий елемент (поза стилю), то одним з його атрибутів є TargetType, Що задає область дії шаблону по відношенню до зазначених елементів

Елемент ControlTemplate визначає дерево елементів, які описують нове уявлення для обраного елемента Оскільки дерево елементів може бути тільки один і повинно містити батьківський елемент, то всередині ControlTemplate зазвичай вказується один з доступних контейнерів У разі кнопки цим контейнером є Grid Всередині контейнера задаються дочірні елементи, що описують нове уявлення кнопки, а також анімацію, повязану з переходом зі стану в стан Таким чином, все досить просто: щоб створити свій власний елемент на основі існуючого, досить визначити його подання (іноді базуючись на деяких обовязкових елементах), а також анімації, супроводжуючі елемент в певних станах

Природно, якщо ми визначаємо елемент, що не описуючи новий ControlTemplate, То елемент використовує стандартне уявлення, описане при створенні елемента Це подання можна легко отримати, скориставшись утилітою Expression Blend 5, про яку піде мова в наступному розділі Ця утиліта вміє копіювати вбудований в елемент шаблон, дозволяючи редагувати його у вигляді ресурсів або вбудованого в сторінку стилю і використовувати його для всіх аналогічних елементів управління

Щоб подивитися на шаблон, генерований Expression Blend 5, створіть порожній проект і додайте на сторінку додатка кнопку Клацнувши правою кнопкою на новоствореному елементі управління, виберіть команду контекстного меню Edit Template -&gt Edit a Copy:

Рис 81

Ця команда дозволяє витягти зумовлений шаблон в ресурси програми у вигляді стилю сторінки або в окремий файл ресурсів При цьому можна застосувати створений стиль до всіх аналогічним елементами (на сторінці або в додатку)

Рис 82

Згенерувавши ресурси, можна перейти в режим редагування копії шаблону для створення нової обгортки елемента керування Звертаємо Вашу увагу, що Blend вбудовує шаблон елемента в стиль, задаючи властивість Template Адже стиль дозволяє задати додаткові властивості елемента і є більш зручним

Для найпростіших елементів, таких як кнопки, можна задавати абсолютно довільне уявлення У складніших випадках елемент може задавати список частин, які повинні обовязково входити в його складові Елементи управління, обовязкові для створення нового шаблону називаються Parts (Частини) Щоб вказати на всі частини, елемент використовує спеціальний атрибут TemplatePart:

 [TemplatePart(Name = &quotTextElement&quot, Type = typeof(TextBlock))] [TemplatePart(Name = &quotUpButtonElement&quot, Type = typeof(RepeatButton))] [TemplatePart(Name = &quotDownButtonElement&quot, Type = typeof(RepeatButton))] public class MyControl: Control

У цьому коді декларується новий елемент управління, у візуальній частині якого зобовязані бути присутніми три елементи: текстовий блок і два елементи типу RepeatButton Даний код надуманий і скоріше є винятком, так як нові елементи управління намагаються обійти використання подібних атрибутів, реалізуючи інтерфейси і універсальне поведінку

Отже, розібравшись з складовими елемента керування, заглибимося в аналіз поведінки кнопки Справа в тому, що кнопка змінює своє зовнішнє подання залежно від поведінки користувача і руху миші Щоб визначити поведінку кнопки в кожному з її станів, необхідно:

·&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp описати можливі стану

·&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp модифікувати поточний стан всередині логіки елемента управління

·&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp описати зміни для кожного з станів в XAML

·&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp визначити додаткові характеристики переходу з одного стану в інший

Щоб описати можливі стану всередині логіки елемента керування, використовується атрибут класуTemplateVisualState Для опису елемента управління Button використовується цілих сім подібних атрибутів:

 [TemplateVisualState(Name = &quotNormal&quot, GroupName = &quotCommonStates&quot)] [TemplateVisualState(Name = &quotPointerOver&quot, GroupName = &quotCommonStates&quot)] [TemplateVisualState(Name = &quotPressed&quot, GroupName = &quotCommonStates&quot)] [TemplateVisualState(Name = &quotDisabled&quot, GroupName = &quotCommonStates&quot)] [TemplateVisualState(Name = &quotUnfocused&quot, GroupName = &quotFocusStates&quot)] [TemplateVisualState(Name = &quotFocused&quot, GroupName = &quotFocusStates&quot)] [TemplateVisualState(Name = &quotPointerFocused&quot, GroupName = &quotFocusStates&quot)]

public class Button : ButtonBase

{

}

З наведеного синтаксису нескладно здогадатися, що атрибут приймає два параметри: імя стану та імя групи Групи вводяться для того, щоб обмежити можливість перетину станів Так, кнопка не може бути натиснута і відпущена одночасно, вона може знаходитися тільки в одному стані з кожної групи

Щоб забезпечити перехід зі стану в стан, всередині реалізації логіки елемента керування досить скористатися статичним методом GoToState класу VisualStateManager:

private void UpdateStates(bool useTransitions)

{

if (isFocused)

{

VisualStateManagerGoToState(this, &quotFocused&quot, useTransitions)

}

else

{

VisualStateManagerGoToState(this, &quotUnfocused&quot, useTransitions)

}

}

Тут метод приймає імя властивості і визначає, чи може використовуватися додаткова анімація при переході з одного стану в інший

Саме методGoToState  ми використовували при визначенні поведінки додатки в різних режимах (Snapped, Filled і т д)

Тепер можна перейти до XAML Тут і виконується вся робота по зміні візуального представлення елемента при переході з одного стану в інший Це робиться за допомогою елементаVisualStateManager, Який містить опис всіх станів (VisualState), Розбитих на групи (VisualStateGroup):

&ltVisualStateManagerVisualStateGroups&gt

&ltVisualStateGroup x:Name=&quotCommonStates&quot&gt

&ltVisualState x:Name=&quotNormal&quot/&gt

&ltVisualState x:Name=&quotPointerOver&quot&gt

&ltStoryboard&gt

&ltObjectAnimationUsingKeyFrames StoryboardTargetName=&quotBackgroundGlyph&quot StoryboardTargetProperty=&quotForeground&quot&gt

&ltDiscreteObjectKeyFrame KeyTime=&quot0&quot Value=&quot{StaticResource

AppBarItemHoverBackgroundBrush}&quot/&gt

&lt/ObjectAnimationUsingKeyFrames&gt

&ltObjectAnimationUsingKeyFrames StoryboardTargetName=&quotContent&quot StoryboardTargetProperty=&quotForeground&quot&gt

&ltDiscreteObjectKeyFrame KeyTime=&quot0&quot

Value=&quot{StaticResource AppBarItemHoverForegroundBrush}&quot/&gt

&lt/ObjectAnimationUsingKeyFrames&gt

&lt/Storyboard&gt

&lt/VisualState&gt

&ltVisualState x:Name=&quotPressed&quot&gt

.

Тут все виглядає досить просто У кожному з станів запускається серія анімацій, що змінюють властивості складових кнопки

Напевно, Ви звернули увагу, що кожна анімація має властивість KeyTime або Duration, Якому присвоєно значення 0 Це означає, всі зміни відбуваються миттєво Щоб зробити анімацію більш плавною, користуються спеціальним елементомVisualTransition, Який і дозволяє задати час виконання всього StoryBoard

&ltVisualTransition From=&quotNormal&quot GeneratedDuration=&quot0:0:3&quot To=&quotPointerOver&quot/&gt

Таким чином, створення шаблону – завдання тривіальна Тим часом, Expression Blend дозволяє ще більше спростити цю задачу, надаючи спеціальний режим редагування шаблону У цьому режимі розробник отримує доступ до таких вікнам, як States і Parts, А також до всього дереву елемента керування Вікно Parts дозволяє відобразити всі обовязкові елементи, що дає можливість відслідковувати помилки створення шаблону і позбавляє від необхідності вивчати документацію для кожного елемента, щоб дізнатися, які у нього обовязкові складові Вікно States відображає всі стани, розбиті по групах, з можливістю створювати переходи і редагувати анімацію в кожному з станів

Рис 83

Сергій Лутай, Сергій Байдачний, Windows 8 для C # розробників

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*