Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Windows Presentation Foundation.docx
Скачиваний:
14
Добавлен:
13.08.2019
Размер:
1.13 Mб
Скачать

2. ПРостейшее ПриложениеWpf

Следующий листинг описывает простейшее приложение WPF, включающее единственное окноинтерфейса:

//файлprogram.cs

using System;

using System.Windows;

classProgram

{

[STAThread]

staticvoid Main()

{

Window myWin = newWindow();

myWin.Title = "First Program";

myWin.Content = "Hello, world";

Application myApp = newApplication();

myApp.Run(myWin);

}

}

Проанализируем данный код. Пространство имён System.Windows содержит классы Window и Application, описывающее окно и приложение соответственно.Точка входа помечена атрибутом [STAThread]. Это является обязательным условием для любого приложенияWPF и связано с моделью многопоточности, применяемой в WPF.В методе Main() создаётся и настраивается объект окна, затем создаётся объект приложения. Вызов myApp.Run(myWin) приводит к отображению окна myWin и запуску цикл обработки событий.

Скомпилируем программу при помощи компилятора командной строки:

csc.exe/r:PresentationCore.dll;PresentationFramework.dll;WindowsBase.dll

/t:winexeprogram.cs

Припомощиключа/rустанавливаютсяссылкинасборкиPresentationFramework.dll, PresentationCore.dllиWindowsBase.dllсклассамиWPF.Ключ /t:winexe указывает, что создаётся оконное приложение.

Отметим, что наше приложение допускает другую организацию. Вместо настройки объекта Window можно создать наследник этого класс и выполнить установку параметров в конструкторе наследника или в специальном методе:

// наследник класса Window, описывающий пользовательское окно

classMyWindow : Window

{

public MyWindow()

{

Title = "First Program";

Content = "Hello, world";

}

}

ВVisualStudioприложениям WPFсоответствует отдельный шаблон проекта. Этот шаблон ориентирован на использование XAML, поэтому в случае однооконного приложения VisualStudioсоздаст следующий набор файлов:

  • файлы Window1.xaml.csи Window1.xaml (на языке XAML) описывают класс Window1, являющийся наследником класса Window;

  • файлы App.xaml.csи App.xamlописывают класс App– наследник класса Application.

Ниже приведён файлWindow1.xamlдля простейшего окна:

<Window x:Class="WpfApplication.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="First Program" Height="300" Width="300">

Hello, world

</Window>

VisualStudioвыполняеткомпиляциюпроектаWPFвдваэтапа.Вначале для каждого файлаXAML генерируется два файла, сохраняемых в подкаталогахobj\Debug или obj\Release (в зависимости от цели компиляции):

  • файл с расширением *.baml – двоичное представление XAML-файла, внедряемое в сборку в виде ресурса (BAML-файл);

  • файл с расширением *.g.cs – разделяемый класс, который соответствует XAML-описанию. Этот класс включает поля для всех именованных элементов файла XAML и реализацию метода InitializeComponent(), загружающего BAML-данные из ресурсов сборки. Кроме этого, класс содержит метод, подключающий все обработчики событий.

На втором этапе сгенерированные файлы компилируются вместе с исходными файламиC# в единую сборку (рис. 2).

Рис. 2. Компиляция WPF-приложения в VisualStudio.

3. XAML

XAML (ExtensibleApplicationMarkupLanguage, расширяемый язык разметки приложений) –это язык разметки, предлагающий основанный на XML синтаксис для представления логического дерева объектов .NET.

Существует несколько подмножеств XAML:

  • WPF XAML включает элементы, описывающие содержимое WPF вроде векторной графики и элементов управления;

  • XPS XAML– часть WPF XAML, определяющая XML-представление форматированных электронных документов. Эта часть опубликована как отдельный стандарт XML PaperSpecification (XPS);

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

  • WF XAML включает элементы, описывающие содержимое WindowsWorkflowFoundation.

Рассмотрим основные правила XAML.Документ XAMLзаписан в формате XML. Это означает, что именаэлементовXAML чувствительны к регистру,нужна правильная вложенность элементов, некоторые символы требуют особого обозначения (например, &–это символ &).

Объектные элементы XAMLописывают объект некоторого типа .NET (класса или структуры).Имя объектного элемента совпадает с именем типа. Необходимо, чтобы тип обладал открытым конструктором без параметров. Например, следующий объектный элемент описывает объект Button (кнопку):

<Button>Click me!</Button>

Типы .NET обычно вложены в пространства имён. В XAMLпространство имён .NETставится в соответствие пространству имён XML. Для этого используется следующий синтаксис:

xmlns:префикс="clr-namespace:ПространствоИмён"

При необходимости указывается сборка, содержащая пространство имён:

xmlns:префикс="clr-namespace:ПространствоИмён;assembly=ИмяСборки"

WPFXAMLобычноиспользует два стандартных пространства имён:

  • http://schemas.microsoft.com/winfx/2006/xaml/presentation–соответствует набору пространств имён .NETс классамиWPF;

  • http://schemas.microsoft.com/winfx/2006/xaml– содержит классы, используемые анализатором XAML (XAMLparser).

Любые пространства имён,как правило, описываются в корневом элементе XAML. При этом первое из стандартных пространств имён обычно указывается без префикса, а значит, применяется по умолчанию ко всем элементам.Пространство имён анализатора XAML традиционно указывается с префиксом x.

<Windowxmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:sys="clr-namespace:System;assembly=mscorlib">

<Button>Click me!</Button>

</Window>

Описание объекта подразумевает заданиезначений его свойств. В XAMLдля этого применяются атрибуты, элементы свойств и содержимое элемента.При использовании атрибутов указывается имя свойства и значение свойства в виде строки:

<Button Width="100" Foreground="Red">Click me!</Button>

Анализатор XAML применяет для преобразования строки в значение свойства специальные конвертеры типов. Набор стандартных конвертеров достаточно богат.При необходимости можно разработать собственный конвертер, используя базовый класс TypeConverter.

Элемент свойства – это дочерний элемент объектного элемента, имеющий вид<TypeName.Property>. Содержимое элемента свойства рассматривается как значение свойства:

<Button>

<Button.Width>100</Button.Width>

<Button.Foreground>Red</Button.Foreground>

Click me!

</Button>

Тип, соответствующий объектному элементу, может быть помеченатрибутом[ContentProperty]с указанием имени свойства содержимого.В этом случае анализатор XAMLрассматриваетсодержимое объектного элемента как значение свойства содержимого. Например, в классе Button свойством содержимого является Content1:

[System.Windows.Markup.ContentProperty("Content")]

publicclassButton{ . . . }

Это означает, что следующие два фрагмента XAMLэквиваленты:

<ButtonContent="Click me!"/>

<Button>Click me!</Button>

Если тип реализует интерфейсы IList или IDictionary, при описании объектаэтого типа в XAMLдочерние элементы автоматически добавляются в соответствующую коллекцию. Например, свойство ItemsклассаListBox имеет тип ItemCollection, который реализует IList:

<ListBox>

<ListBox.Items>

<ListBoxItem Content="Item 1"/>

<ListBoxItem Content="Item 2"/>

</ListBox.Items>

</ListBox>

Кроме этого, Items – это свойство содержимого для ListBox, а значит,XAML-описание можно упростить:

<ListBox>

<ListBoxItem Content="Item 1"/>

<ListBoxItem Content="Item 2"/>

</ListBox>

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

Технически, любое расширение разметки – это класс, унаследованный от класса MarkupExtension и перекрывающий функцию ProvideValue():

using System;

using System.Windows.Markup;

namespace MarkupExtensions

{

publicclassShowTimeExtension : MarkupExtension

{

public ShowTimeExtension() { }

public ShowTimeExtension(string header)

{

Header = header;

}

publicstring Header { get; set; }

publicoverrideobject ProvideValue(IServiceProviderprovider)

{

returnstring.Format("{0}: {1}", Header, DateTime.Now);

}

}

}

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

<Window xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:local="clr-namespace:MarkupExtensions">

<StackPanel>

<Button Content="{local:ShowTime First}"/>

<Button Content="{local:ShowTime Header=Second}"/>

</StackPanel>

</Window>

Расширения разметки могут применяться и в виде вложенных элементов:

<Button>

<Button.Content>

<local:ShowTime Header="First" />

</Button.Content>

</Button>

Втабл. 1 представлены стандартные расширения разметки, доступные после подключения пространства имён анализатора XAML.

Таблица 1

Стандартные расширения разметки

Имя

Описание

x:Array

Представляет массив. Дочерние элементы становятся элементами массива:

<x:Array Type="{x:Type Button}">

<Button />

<Button />

</x:Array>

x:Null

Значениеnull

Background="{x:Null}"

x:Static

Представляет статическое свойство, поле или константу:

Height="{x:Static SystemParameters.IconHeight}"

x:Type

Аналог применения оператора typeof из языка C#

Анализатор XAMLгенерирует код, выполняющий по документу XAMLсоздание и настройку объектов. Действия с объектами описываются в отдельном классе кода. Чтобы сослаться на объект в коде, объект должен иметь имя. Для этого в пространстве имён анализатора XAMLопределён атрибут Name:

<Buttonx:Name="okButton"Content="Click me!"/>

Заметим, что многие элементы управления WPF имеют свойство Name. Анализатор XAML использует соглашение, по которому задание свойства Name эквивалентно указанию XAML-атрибута x:Name.

Чтобы связать класс кода с документом XAMLиспользуется атрибут Class из пространства имён анализатора XAML. Этот атрибут применяется только к корневому элементу и содержит имя класса, являющегося наследником класса корневого элемента:

<Window x:Class="WpfApplication1.MainWindow"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Buttonx:Name="okButton" Content="Click me!"/>

</Window>

В заключение заметим, что WPF XAMLописывает логическое дерево элементов. Наряду с этим термином используется понятие визуального дерева элементов. Визуальное дерево составляют отображаемые объекты. Некоторые одиночные логические объекты распадаются на несколько визуальных составляющих, так как строятся из нескольких визуальных примитивов. Например, любое окно Window включает визуальный примитив Border, который содержит примитив AdornerDecoratorc объектами ContentPresenterи AdornerLayer.