Спонсор: Microsoft
Опубликован: 13.12.2011 | Доступ: свободный | Студентов: 982 / 29 | Оценка: 4.29 / 4.57 | Длительность: 13:56:00
Лекция 1:

Краткое знакомство с моделью программирования XAML

Ресурсы и стили

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

<Canvas xmlns="http://schemas.microsoft.com/2003/xaml">
    <Canvas.Resources>
        <SolidColorBrush def:Name="MyFavoriteColor" Color="Magenta"/>
    </Canvas.Resources>
</Canvas>

определяет ресурс под именем MyFavoriteColor типа SolidColorBrush с заданным значением цвета кисти, который мы можем переиспользовать в любом контексте, в котором ожидается кисть, например:

<Button Background="{MyFavoriteColor}"/>

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

<Style def:Name="MagentaButtonWithLargeFont">
    <Button Background="{MyFavoriteColor}" FontSize="100">
</Style>

и который затем можно применить к кнопке:

<Button Style="{MagentaButtonWithLargeFont}">My Magenta Button</Button>

Интересным применением стилей является изменение внешнего вида контролов по событиям. Так, например, вы можете изменить стиль кнопки по наведению на нее мышки, что может быть описано в теле стиля с помощью тега PropertyTrigger.

Каждый тэг XAML соответствует классу объектной модели WPF. Тэг обычно имеет набор атрибутов, которые соответствуют свойствам этого класса. Во время компиляции парсер по XAML-описанию порождает частичный (partial) класс, который содержит эквивалентный код. Каждый тэг XAML становится экземпляром соответствующего класса объектной модели, значения атрибутов тэга присваиваются соответствующим свойствам этого объекта. Затем частичный класс, порожденный из XAML, объединяется с code-behind кодом, написанным программистом. Все это дает нам возможность, кроме всего прочего, порождать интерфейс на лету.

Разделение труда дизайнера и разработчика

Как выглядит общение дизайнера и разработчика в настоящий момент? Как правило, дизайнер создает макет пользовательского интерфейса в графическом редакторе, на бумаге или с помощью какого-либо другого средства – любого, кроме средства разработки приложения. Как следствие, конкретную реализацию мечтаний дизайнера все равно создает программист. Это ведет к тому, что, во-первых, дизайнер может создать макет UI, который в принципе нереализуем или труднореализуем, а во-вторых, программист может ошибиться в реализации или же по-своему интерпретировать те или иные пожелания дизайнера. В итоге дизайнер вынужден пересматривать получившееся творение и высказывать пожелания к улучшению интерфейсов. Таким образом, разработка UI превращается в многоэтапный итеративный процесс, тормозящий основную разработку. С помощью WPF станет возможным исключить такие ситуации. Наличие в нем общего знаменателя – языка описания интерфейсов XAML – позволит разделить работу дизайнера и программиста. В самом деле, программисту от XAML в основном нужны только имена элементов управления и обработчики их событий, которые он использует в своей программе. Дизайнер же может спокойно разрабатывать UI в инструментах, более приспособленных для этой задачи, а не в непонятных ему средах разработки приложений.

XAML – текущая поддержка

Итак, для разделения труда программиста и разработчика нам нужны соответствующие интегрированные средства для работы с XAML в IDE и в графических редакторах. Таким средства есть:

  • Visual Designer for the Windows Presentation Foundation (ранее известный как Cider) – это то, с чем работает программист в Visual Studio при разработке. Visual Designer для WPF станет частью Visual Studio в ее следующей версии, Orcas, поддерживающей Vista.
  • Expression Graphic Designer (бывшая Acrylic), программа для работы с 2D-графикой, – это то, с чем работает дизайнер вне всяких IDE. В Graphic Designer сделан упор на внешний вид приложений
  • Expression Interactive Designer (ранее известный как Sparkle) – инструмент для создания 3D-анимации и графики. Interactive Designer уделяет внимание "поведению и взаимодействию"
  • Expression Web Designer (бывший Quartz) – инструмент для разработки веб-страниц. По сути новая и улучшенная версия FrontPage, предназначенная для разработки пользовательского интерфейса и верстки веб-страниц и Windows-приложений. Тесно интегрируется с ASP .NET 2.0 (в частности, "знает" о контролах ASP.NET, смарт-тэгах и т.п.)
  • XAMLPAD – названный, видимо, по аналогии с NotePad, несложный инструмент редактирования XAML.

Семейство Expression-редакторов работает как с векторной графикой (напомним, что движок WPF – векторный), так и с растровыми изображениями.

Модель программирования XAML

Язык XAML обладает дополнительной по сравнению с XML семантикой, которая допускает единую интерпретацию. Слегка упрощая, можно сказать, что XAML - это основанный на XML сценарный язык для создания объектов CLR. Имеется соответствие между XML-тегами и типами CLR, а также между XML-атрибутами и свойствами и событиями CLR. В следующем примере показано, как создать объект и присвоить значение его свойству на языках XAML и C#:

<!— версия на XAML —>
<MyObject SomeProperty='1' />

// версия на C#
MyObject obj = new MyObject(); 
obj.SomeProperty = 1;

XML-теги всегда определяются в контексте некоторого пространства имен, которое и описывает, какие теги являются допустимыми. В XAML пространства имен в смысле XML отображаются на наборы пространств имен и сборок в смысле CLR. Чтобы приведенный выше простой пример заработал, необходимо установить соответствие между требуемыми пространствами имен. В XML для определения новых пространств имен применяется атрибут xmlns:

<!— версия для XAML —>
<MyObject  xmlns='clr-namespace:Samples' SomeProperty='1' />
// версия для C# 
using Samples;
MyObject obj = new MyObject(); 
obj.SomeProperty = 1;

В C# перечень сборок, в которых находятся используемые типы, всегда задается в файле проекта или с помощью аргументов командной строки для запуска компилятора csc.exe. В XAML можно определить местоположение исходной сборки для каждого пространства имен:

<!— версия для XAML —>
<MyObject xmlns='clr-namespace:Samples; assembly=samples.dll'
  SomeProperty='1'/>
// версия для C#
csc /r:samples.dll test.cs
using Samples;
MyObject obj  = new MyObject();
obj.SomeProperty = 1;

В XML мир разбит на две половины: элементы и атрибуты. Модель XAML более тесно связана с CLR, поскольку апеллирует к объектам, свойствам и событиям. Значения свойств можно представлять в виде атрибутов или дочерних элементов. Предыдущий пример допустимо записать и так:

<MyObject  xmlns='clr-namespace:Samples, assembly=samples.dll'>
    <MyObject.SomeProperty>
 
    </MyObject.SomeProperty>
</MyObject> 

Каждый элемент, соответствующий свойству, квалифицируется типом, которому это свойство принадлежит. Предположим, например, что есть еще одно свойство, значением которого является объект типа Person со свойствами FirstName и LastName. На XAML можно было бы легко выразить это соотношение, воспользовавшись элементами для описания свойств:

<MyObject  xmlns='clr-namespace:Samples, assembly=samples.dll'>
    <MyObject.Owner>
        <Person FirstName='Chris' LastName='Anderson' />
    </MyObject.Owner>
</MyObject>

XAML проектировался как язык разметки, тесно интегрированный с CLR и обеспеченный развитой инструментальной поддержкой. Дополнительно ставилась цель создать такой формат, который было бы легко читать и записывать. Может показаться, что проектировать свойство платформы, которое оптимизировано прежде всего для инструментов, а лишь потом для людей, не слишком вежливо, но команда WPF полагала, что приложения для WPF как правило будут создавать с помощью таких программ визуального конструирования, как Microsoft Visual Studio или Microsoft Expression. Чтобы граница между инструментами и людьми не была непроходимой, WPF позволяет автору типа определить одно свойство как контентное.

В примере выше, если сделать свойство Owner типа MyObject контентным , то в разметке можно будет опустить тег элемента, соответствующего этому свойству:

<MyObject  xmlns='clr-namespace:Samples; assembly=samples.dll'>
    <Person FirstName='Megan' LastName='Anderson'   /> 
</MyObject>

Чтобы воспринимать текст было еще удобнее, в XAML есть возможность расширения разметки. Это общий способ расширить синтаксический анализатор языка с целью создания более простой разметки. Расширения реализуются в виде типов CLR и работают почти так же, как атрибуты CLR. Они заключаются в фигурные скобки { }. Например, чтобы присвоить свойству специальное значение null, можно воспользоваться встроенным расширением разметки Null:

<MyObject   xmlns='clr-namespace:Samples; assembly=samples.dll'>
    <Person FirstName='Megan' LastName='{x:Null}'/> 
</MyObject>

В таблице 1.1 перечислены все встроенные расширения XAML.

Таблица 1.1. Встроенные расширения XAML
Пространство имен XAML Назначение Пример
x:Array Создает массив CLR
<x:Array Type='{x:Type Button}'>
     <Button  />
          <Button  />
</x:Array>
x:Class Задает имя определяемого типа (используется только при компиляции разметки)
<Window
      x:Class = 'MyNamespace.MyClass '>
            ...
      </Window>
X:ClassModifier Задает модификаторы определяемого типа ("public" "intemal" и т.д.) (используется только при компиляции разметки)
<Window x:Class='...'
                 x:ClassModifier='Public'>
</Window>
x:Code Ограничивает блок встроенного кода (используется только при компиляции разметки)
<Window x:Class='...'>
    <x:Code>
           public void DoSomething()
      {
             }
                </x:Code>                
                </Window>
x:Key Задает ключ элемента (поддерживается только для элементов, содержащихся в словарях)
<Button>    
  <Button.Resources>        
    <Style x:Key='Hi'>...</Style>    
       </Button.Resources></Button>
x:Name Задает имя элемента для ссылки на него в программе (обычно используется, когда у элемента нет встроенного свойства name)
<sys:Int32
                   xmlns:sys = 'clr-namespace: System;...'
x:Name = '_myIntegerValue'> 5
  </sys:Int32>
x:Null Создает значение null. <Button Content = '{x:Null}' />
x:Static Создает значение путем доступа к статическому полю или свойству типа.
<Button
    Command = '{x:Static 
ApplicationCommands.Close}'   />
x:Subclass Предоставляет базовый тип для компиляции разметки на язык, в котором не поддерживаются частичные типы.
x:Type Предоставляет тип CLR (эквивалент Type.GetType).
<ControlTemplate
       TargetType='{x:Type Button}'>
</ControlTemplate>
x:TypeArguments Задает обобщенные аргументы типа для создания экземпляра обобщенного типа.
<gc:List xmlns:gc='clrnamespace:
                   System.Collections.Generic;...'
                   x:TypeArguments ='{x:Type Button}'/> 
x:XData Ограничивает блок встроенного XML; может использоваться только для свойств типа IXmlSerializable.
<XmlDataSource>
    <x:XData>
            <Book xmlns="  Title='...' />
        </x:XData>
</XmlDataSource>

Расширения разметки ищутся точно также, как теги объектов, то есть необходимо объявить XML-префикс "x", иначе синтаксический анализатор выдаст ошибку. В языке XAML определено специальное пространство имен для встроенных типов:

<MyObject 
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' 
    xmlns='clr-namespace:Samples,-assembly=samples.dll'>

    <Person FirstName='Megan' LastName='{x:Null}' />
</MyObject>

Кроме того, для любой сборки CLR (или набора таких сборок) можно определить имя, построенное по принципу URI и соответствующее пространствам имен и сборок CLR. Это можно считать эквивалентом старого доброго предложения #include 'windows.h', которое хорошо известно программистам на C/C++. В сборках WPF этот механизм применяется, поэтому для импорта WPF в XAML-файл можно использовать любой формат:

<!— вариант 1:  импорт по пространству имен CLR —> 
<Window
    xmlns:x='http://schemas.microsoft.com/winfx/2 0 06/xaml'
    xmlns='clr-namespace:System.Windows;assembly=presentationframework.dll'>
</Window>

<!— вариант 2:  импорт по URI —>
<Window
    xmlns:x='http://schemas.microsoft.com/winfx/2 0 06/xaml' 
    xmlns='http://schemas.microsoft.com/winfx/2 006/xaml/presentation'> 
</Window>

Метод с применением синтаксиса URI хорош тем, что импортируются сразу несколько пространств имен и сборок CLR, а, значит, разметка получается более компактной и работать с ней проще.

В завершении лекции, нужно сказать о такой возможности XAML, как способность расширять типы за счет свойств, предоставляемых другими типами. Такие присоединенные свойства - это просто безопасный относительно типов вариант добавленных свойств (expando properties) в языке JavaScript. В версии XAML, предназначенной для WPF, присоединенные свойства работают только, если и тип, в котором свойство определено, и тип, к которому оно присоединяется, наследуют классу DependencyObject. Однако в общей спецификации XAML такого требования нет.

В следующем примере свойство Dock определено в типе DockPanel. Присоединенному свойству всегда предшествует имя предоставляющего его типа, даже если такое свойство употребляется в качестве атрибута:

<Window
    xmlns:x='http://schemas.microsoft.com/winfx/2 0 06/xaml'
    xmlns='http://schemas.microsoft.com/winfx/2 006/xaml/presentation'>
    <DockPanel>
        <Button DockPanel.Dock='Top'>Top</Button>
        <Button>
            <DockPanel.Dock>Left</DockPanel.Dock>
             Left
        </Button>
        <Button>Fill</Button>
    </DockPanel>
</Window> 

XAML - довольно простой язык, в нем не очень много правил. В версии, которая поставляется в составе .NET Framework 3.0 (4.0), все определения тегов XAML реализованы в виде типов CLR. Поэтому все, что можно сделать с помощью разметки, можно написать и в виде компилируемой программы.

Ключевые термины

API (Windows API англ. application programming interfaces) — общее наименование целого набора базовых функций интерфейсов программирования приложений операционных систем семейств Windows и Windows NT корпорации "Майкрософт". Является самым прямым способом взаимодействия приложений с Windows. Для создания программ, использующих Windows API, "Майкрософт" выпускает SDK, который называется Platform SDK и содержит документацию, набор библиотек, утилит и других инструментальных средств.

CLR (Common Language Runtime) — "общеязыковая исполняющая среда" — компонент пакета Microsoft .NET Framework, исполняющий программы, написанные на .NET-совместимых языках программирования.

CSS (англ. Cascading Style Sheets — каскадные таблицы стилей) — формальный язык описания внешнего вида документа, написанного с использованием языка разметки.

Silverlight — это программная платформа, включающая в себя плагин для браузера, который позволяет запускать приложения, содержащие анимацию, векторную графику и аудио-видео ролики, что характерно для RIA (Rich Internet application).

UI (англ. user interface) — разновидность интерфейсов, в котором одна сторона представлена человеком (пользователем), другая — машиной/устройством. Представляет собой совокупность средств и методов, при помощи которых пользователь взаимодействует с различными, чаще всего сложными, машинами, устройствами и аппаратурой.

URI (англ. Uniform Resource Identifier) — унифицированный (единообразный) идентификатор ресурса. URI — это последовательность символов, идентифицирующая абстрактный или физический ресурс. Ранее назывался Universal Resource Identifier — универсальный идентификатор ресурса.

WPF (Windows Presentation Foundation, кодовое название — Avalon) — система для построения клиентских приложений Windows с визуально привлекательными возможностями взаимодействия с пользователем, графическая (презентационная) подсистема в составе .NET Framework (начиная с версии 3.0), имеющая прямое отношение к XAML.

XAML (англ. eXtensible Application Markup Language — расширяемый язык разметки приложений — основанный на XML язык разметки для декларативного программирования приложений, разработанный Microsoft.

XML (англ. eXtensible Markup Language — расширяемый язык разметки) — рекомендованный Консорциумом Всемирной паутины язык разметки, фактически представляющий собой свод общих синтаксических правил. XMLтекстовый формат, предназначенный для хранения структурированных данных (взамен существующих файлов баз данных), для обмена информацией между программами, а также для создания на его основе более специализированных языков разметки (например, XHTML).

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

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

Набор для практики

Вопросы:

  1. Имеется ли возможность вложенности друг в друга у элементов XAML?
  2. Сколько корневых элементов может иметь XAML-документ?
  3. Поясните назначение пространства имен x:Static.
  4. Имеется ли возможность реализовать в виде типов CLR теги XAML?
  5. Приведите синтаксис присоединения обработчиков событий.
Игорь Ключников
Игорь Ключников
Россия
Михаил Ковязо
Михаил Ковязо
Россия, Москва, ВЗМИ, 1982