Побудова базових інтерфейсів XAML

Незалежно від того, використовуєте Ви C # або С + + для розробки своїх Windows 8 додатків, Ви будете використовувати XAML, за допомогою якого в додатку описується більшість інтерфейсних елементів, стилів і ресурсів

XAML (eXtensible Application Markup Language) являє собою декларативний мову, побудований на базі XML Основне призначення цієї мови полягає в описі інтерфейсу програми XAML може бути знаком розробникам за такими технологіями, як Windows Presentation Foundation і Silverlight XAML також застосовується в Workflow Foundation для опису робочих процесів

Щоб краще зрозуміти призначення XAML, досить згадати, як створювалися інтерфейси на мові програмування C # при використанні Windows Forms Так, шматок коду, створює невелику кнопку, міг виглядати наступним чином:

thismyButton = new SystemWindowsFormsButton() thismyButtonLocation = new SystemDrawingPoint(120, 60)

thismyButtonName = &quotmyButton"

thismyButtonSize = new SystemDrawingSize(110, 40) thismyButtonText = &quotHello"

thisControlsAdd(thismyButton)

З одного боку, наведений вище код є громіздким, а з іншого, він не дає розуміння того, як влаштований інтерфейс Дуже складно простежити залежності між контейнерами і зрозуміти структуру інтерфейсу Крім того, якщо ви стикалися з візуальним дизайнером додатків WinForms, то знаєте, що код, згенерований дизайнером, краще не модифікувати По-перше, дизайнер може його просто не розпізнати, а по-друге, всі «ручні» зміни можуть бути видалені при будь-якої модифікації інтерфейсу Це повязано з тим, що розібрати і обробити код, написаний на C #, досить складно Крім того, код може містити вставки, не повязані з побудовою інтерфейсу

Розглянемо аналогічний код на XAML:

&ltCanvas x:Name=&quotLayoutRoot&quot&gt

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot x:Name=&quotmyButton&quot&gt&lt/Button&gt

&lt/Canvas&gt

Як видно, XAML є більш інтуїтивним, ніж код на C #, не тільки для розробників, а й для інших членів команди, наприклад дизайнерів Це дозволяє використовувати XAML для створення прототипів інтерфейсів і переводити їх на стадію розробки, використовуючи один і той же код

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

Представляючи XAML як мова опису інтерфейсу, слід зазначити, що не всі елементи цієї мови мають візуальне уявлення Існують елементи, які задають анімацію або трансформацію, роботу з мультимедіа і пр З ними ми будемо знайомитися в інших розділах

А зараз перейдемо до вивчення синтаксису XAML

Якщо Ви володієте XML, то вивчення XAML для Вас не складе особливих труднощів Як і в XML, будь-який елемент представлений тегом, який може мати атрибути та дочірні елементи Атрибути перераховуються в тезі елемента зі значеннями у вигляді текстових рядків, а дочірні елементи задаються між відкриває і закриває тегами основного елемента:

&ltCanvas Name=&quotLayoutRoot&quot&gt

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot Name=&quotbutton1&quot&gt&lt/Button&gt

&lt/Canvas&gt

Код вище описує елемент Canvas з одним атрибутом і одним дочірнім елементом (Button) В основному тезі Button встановлено шість атрибутів і жодного дочірнього елемента Як і в XML, тег Button можна було б записати наступним чином (явна відсутність закриває тега):

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot Name=&quotbutton1&quot /&gt

XAML (як і XML) чутливий до регістру символів При цьому регістр має значення для опису не тільки елементів і атрибутів, але і значень атрибутів Так, код нижче створює два обєкти з іменами Button1 і button1:

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot Name=&quotbutton1&quot /&gt

&ltButton Content=&quotHello&quot CanvasTop=&quot160&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot Name=&quotButton1&quot /&gt

Мова XAML досить гнучкий Як і XML, мова XAML дозволяє задавати властивості елементів, як через атрибути, так і за допомогою дочірніх елементів Так, наступні два блоки коду виконують однакову функцію:

Блок 1

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Width=&quot110&quot Height=&quot40&quot Name=&quotbutton1&quot&gt&lt/Button&gt

Блок 2

&ltButton Content=&quotHello&quot CanvasTop=&quot60&quot CanvasLeft=&quot120&quot Name=&quotbutton1&quot&gt

&ltButtonWidth&gt 110

&lt/ButtonWidth&gt

&ltButtonHeight&gt 40

&lt/ButtonHeight&gt

&lt/Button&gt

При цьому через атрибути можна не тільки ставити прості значення, а й створювати більш складні обєкти Розглянемо наступні два блоки коду:

Блок 1

&ltRectangle Width=&quot100&quot Height=&quot50&quot Fill=&quotRed&quot&gt&lt/Rectangle&gt

Блок 2

&ltRectangle Width=&quot100&quot Height=&quot50&quot&gt

&ltRectangleFill&gt

&ltSolidColorBrush Color=&quotRed&quot /&gt

&lt/RectangleFill&gt

&lt/Rectangle&gt

Перший блок коду має більш просту запис, але, як і в другому блоці, для установки значення властивості Fill створюється кисть SolidColorBrush Другий блок також не ідеальний, адже тут за допомогою атрибуту створюється обєкт типу Color, Який також можна розписати через набір дочірніх елементів

Створення обєктів через атрибути можливо за допомогою спеціальних конверторів Насправді, навіть при простій установці значення властивості Width працює конвертор Адже Width  є цілочисловим властивістю, а ми присвоюємо йому текст

Якщо конвертора не вистачає, то його слід дописати самостійно Якщо подивитися на шаблон Blank проекту додатки в стилі Metro, то можна помітити, що там пропонується наступний код:

public sealed class BooleanToVisibilityConverter : IValueConverter

{

public object Convert(object value, Type targetType, object parameter, string language)

{

return (value is bool &amp&amp (bool)value)

VisibilityVisible : VisibilityCollapsed

}

public object ConvertBack(object value, Type targetType, object parameter, string language)

{

return value is Visibility &amp&amp (Visibility)value == VisibilityVisible

}

}

Тут описаний конвертор, який дозволяє виконати перетворення для одного з основних властивостей всіх елементів управління –Visibility Ця властивість приймає значення перечислимого типу Visibility: Collapsed або Visible За допомогою нашого конвертора можна встановити властивості значення змінної типу bool Такий підхід дозволяє спростити роботу з даними при звязуванні Як використовувати конвертори, розглянемо пізніше

Розглянемо два еквівалентних блоку коду:

Блок 1

&ltTextBlock&gt Hello

&lt/TextBlock&gt

Блок 2

&ltTextBlock Text=&quotHello&quot&gt&lt/TextBlock&gt

Як видно, у першому блоці властивість Text елемента TextBlock задається неявно Такий підхід реалізовано для простоти (згадайте, наприклад, синтаксис HTML) використання XAML Будь клас, що описує елемент, може містити лише одне таке властивість (контентне властивість), яке задається за допомогою атрибуту ContentPropertyAttribute при описі класу

Останнім питанням, який ми розглянемо в цьому розділі, є створення колекцій Розглянемо наступний блок коду:

&ltRectangle Width=&quot100&quot Height=&quot50&quot&gt

&ltRectangleFill&gt

&ltLinearGradientBrush&gt

&ltLinearGradientBrushGradientStops&gt

&ltGradientStopCollection&gt

&ltGradientStop Offset=&quot00&quot Color=&quotRed&quot /&gt

&ltGradientStop Offset=&quot10&quot Color=&quotGreen&quot /&gt

&lt/GradientStopCollection&gt

&lt/LinearGradientBrushGradientStops&gt

&lt/LinearGradientBrush&gt

&lt/RectangleFill&gt

&lt/Rectangle&gt

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

Перше, на що потрібно звернути увагу, це те, що властивість GradientStops є контентним, а значить, його можна не писати Тоді весь контент всередині LinearGradientBrush асоціюватиметься саме з GradientStops:

&ltRectangle Width=&quot100&quot Height=&quot50&quot&gt

&ltRectangleFill&gt

&ltLinearGradientBrush&gt

&ltGradientStopCollection&gt

&ltGradientStop Offset=&quot00&quot Color=&quotRed&quot /&gt

&ltGradientStop Offset=&quot10&quot Color=&quotGreen&quot /&gt

&lt/GradientStopCollection&gt

&lt/LinearGradientBrush&gt

&lt/RectangleFill&gt

&lt/Rectangle&gt

Крім того, аналізатор XAML досить «кмітливий», щоб розпізнати тип властивості GradientStops і приготуватися до створення колекції обєктів Тому тип колекції явно задавати не потрібно Таким чином, наш код став ще менше:

&ltRectangle Width=&quot100&quot Height=&quot50&quot&gt

&ltRectangleFill&gt

&ltLinearGradientBrush&gt

&ltGradientStop Offset=&quot00&quot Color=&quotRed&quot /&gt

&ltGradientStop Offset=&quot10&quot Color=&quotGreen&quot /&gt

&lt/LinearGradientBrush&gt

&lt/RectangleFill&gt

&lt/Rectangle&gt

Тим часом, незважаючи на однаковий результат, первісний код і останній блок виконуються по-різному Так, якщо Ви явно вказуєте колекцію, то при запуску програми спочатку генерується обєкт типу колекції, а потім створюються елементи, які поміщаються в створений обєкт, а сам обєкт привласнюється властивості (в даному випадку, Fill) Це дозволяє задати не тільки колекцію елементів, а й імя самої колекції, і звертатися до неї в коді Але, використовуючи такий підхід, слід памятати, що багато колекції не можуть бути створені явно Їх створення приховано всередині дочірнього елемента, і аналізатор XAML просто викликає метод Add без явного створення обєкта типу колекції Тому синтаксис з явною записом типу колекції дуже часто просто неможливий Наприклад, наступний код не працюватиме, оскільки створити явно обєкт типу UIElementCollection неможливо:

&ltStackPanel x:Name=&quotLayoutRoot&quot Background=&quotWhite&quot&gt

&ltStackPanelChildren&gt

&ltUIElementCollection&gt

&ltButton Width=&quot100&quot Height=&quot50&quot&gt&lt/Button&gt

&lt/UIElementCollection&gt

&lt/StackPanelChildren&gt

&lt/StackPanel&gt

А от наступні два блоки будуть працювати чудово:

Блок 1

&ltStackPanel x:Name=&quotLayoutRoot&quot Background=&quotWhite&quot&gt

&ltStackPanelChildren&gt

&ltButton Width=&quot100&quot Height=&quot50&quot&gt&lt/Button&gt

&lt/StackPanelChildren&gt

&lt/StackPanel&gt

Блок 2 (Children – контентний елемент)

&ltStackPanel x:Name=&quotLayoutRoot&quot Background=&quotWhite&quot&gt

&ltButton Width=&quot100&quot Height=&quot50&quot&gt&lt/Button&gt

&lt/StackPanel&gt

Сергій Лутай, Сергій Байдачний, 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>

*

*