250 likes | 567 Views
Литература. Мэтью Мак-Дональд . Windows Presentation Foundation в . NET 3.5 с примерами на C# 2008 для профессионалов - Изд. Вильямс, 2008. Крис Андерсон . Основы Windows Presentation Foundation. – ДМК Пресс, СПб, 2008.
E N D
Литература Мэтью Мак-Дональд . WindowsPresentationFoundationв .NET3.5 с примерами на C# 2008 для профессионалов -Изд. Вильямс, 2008. КрисАндерсон. Основы Windows Presentation Foundation. – ДМК Пресс, СПб, 2008. Петцольд Ч. Microsoft Windows Presentation Foundation. Базовый курс. -Изд. Microsoft Press. Русская редакция, СПб.: Питер, 2008.
Программные модели пользовательского интерфейса Windows API ( Windows 1.0) 1990 Windows API ( Windows 3.0) 1992 MFC (Microsoft Foundation Classes) – библиотека классов C++ 2001 Windows Forms в .NET Framework 1.0 2006 WPF (Windows Presentation Foundation) в .NET Framework 3.0
Цели разработки Windows Presentation Foundation • Основная цель разработки WPF – создать новую унифицированную платформу, которая заменила бы всю инфраструктуру создания приложений на стороне клиента и использовала бы лучшее из Win32 и Web. • В начале 2000-хMicrosoft поддерживала четыре платформы для создания пользовательского интерфейса User32/GDI32, Ruby (формы Visual Basic), Trident (отображение web-страниц в приложениях)и Windows Forms, в основе которых лежали разные модели программирования. • Цели при проектировании WPF: • создать платформу для развитой презентации; • создать платформу, поддерживающую взаимодействие кода и декларативной модели программирования; • стереть границы между Windows и Web.
WPF- Windows Presentation Foundation • Весь вывод происходит через DirectX – интерфейс аппаратно-ускоренной графики. Windows Presentation Foundation WindowsForms PresentationFramework PresentationCore milcore Common Language Runtime DirectX Windows 7 Windows Vista Windows XP Windows Server 2003
Windows Forms и Win32 API • WindowsForms - управляемый API в .NET Framework 1.0, 2.0, 3.x для создания пользовательского интерфейса локальныхприложений. WindowsForms- это фактическиуправляемый слой над User32 и GDI+. • Классы WindowsFormsподдерживают все элементы пользовательского интерфейса Win32. • Некоторые классы описывают элементы управления, работающие только в .NET Framework. • Большая часть типов WindowsFormsопределена в пространстве имен System.Windows.Formsи во вложенных пространствах имен.
WPF и XAML • Одна из задач, которая была решена при проектировании и реализации WPF, -разделение работы между дизайнерами и программистами. • Решение состоит в разделении исходного кода WPF-приложения на две части: • декларативное описание пользовательского интерфейса с использованием языка разметки XAML (EXtensibleApplication Markup Language ); • код на языке программирования, например C#,содержащий обработку событий. • Для компиляции WPF-приложений обычно используется Microsoft Build Engine (MSBuild) –технология, включенная в .NET Framework 3.x в виде набора сборок.
Компиляция WPF приложений • При компиляции XAML файлы разбираются (parsed) и преобразуются в коды на языке BAML ( Binary Application Markup Language), которые встраиваются как ресурс в исполняемый файл. • Код BAML компактнее исходного XAML кода и при выполнении его загрузка выполняется быстрее, чем загрузка XAML файла. • При компиляции для каждого XAML файла создается файл с кодом на языке программирования, содержащий частичное (partial) объявление класса для элемента верхнего уровня в файле разметки. • В общем случае компиляция XAML файловосуществляется в два прохода. • Сначала компилируются только те XAML файлы, которые не содержат ссылки на локально-определенные типы (типы, определенные в данном проекте), так как они существуют только в виде исходного кода и еще не были скомпилированы. • XAML файлы со ссылками на локально-определенные типы компилируются при втором проходе компилятора. • Вся необходимая для работы MSBuildинформация об исходных файлах, ссылках на зависимые сборки и конфигурация приложения находится в файлах проекта MSBuild- XML файлах, подчиняющихся схеме MSBuild.
Элементы XAML • Элементы XAMLотображаются на типы Microsoft .NET, атрибуты элементов XAML на члены этих типов. • Начальное состояние объекта ( object instance) базируется на поведении конструктора без параметров(default constructor). • В примере 1 фрагмент кода XAML содержит элемент Button, отвечающий классу System.Windows.Controls.Button.С использованием синтаксиса атрибутов XAML свойствам Height, HorizontalAlignment,Marginи Nameэлемента Buttonприсвоены значения. <Button Height="23" HorizontalAlignment="Center" Margin="13,0,0,56" Name="button1“ > Get </Button> • В примере 2 код XAML содержит элемент Window, отвечающий классу System.Windows.Window.Элемент Windowсодержит элемент Grid, который в свою очередь содержит элементы Buttonи TextBox. <Window x:Class="Wpf_Sample1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Height="23" HorizontalAlignment="Center" Margin="13,0,0,56“ Name="button1" VerticalAlignment="Bottom" Width="75">Get</Button> <TextBox Height="23" Margin="14,68,18,0" Name="textBox1" VerticalAlignment="Top" /> </Grid> </Window>
Пространства имен XAML • Два пространства имен – пространство имен XAML и пространство имен WPF - присутствуют во всех WPF документах: <Window x:Class="Wpf_Sample1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> </Grid> </Window> • Корневой элемент Windowсодержит атрибуты xmlnsи xmlns:x. Эти атрибуты указывают XAML процессору пространства имен, в которых находятся определения элементов, на которые ссылается разметка. • Атрибут xmlns указывает на пространство имен по умолчанию. Элементы из этого пространства используются в разметке без префикса. • Синтаксический анализатор использует атрибут Class для создания класса, производного от типа, совпадающего именем элемента ( Windowв данном примере). Атрибут Classуказан с префиксом x: , что означает, что это имя находится в пространстве имен XAML.
Пространства имен XAML и WPF • Использование двух пространств имен объясняется тем, что XAML – это стандарт языка, а WPF – одна из реализаций, которая использует XAML как язык. • Реализация WPF резервирует пространство имен по умолчанию для собственного API. Есть соглашение использовать префикс x: для общих конструкций XAML. • Пространству имен, определенному в любой сборке CLR, можно поставить в соответствие имя пространства имен в разметке. В примере пространству имен Labs, определенному в сборке UserLibrary, ставится в соответствие пространство имен в разметке с префиксом my: xmlns:my="clr-namespace:Labs;assembly=UserLibrary” • Классы, определенные в сборке LabsLibrary, можно использовать в разметке, указав их с префиксом my: <Window x:Class="Wpf_Sample1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:my="clr-namespace:Labs;assembly=UserLibrary” Title="Window1" Height="300" Width="300"> <Grid> </Grid> </Window>
Регистр в XAML Правила обработки пробелов в XAML • XAML чувствителен к регистру. Элементы-объекты, имена свойств элементов и имена атрибутов должны с учетом регистра отвечать соответствующим именам в сборках CLR. • Значения атрибутов не всегда чувствительны к регистру, например, преобразователь типа для булевских значений разрешает использовать как true,так и True. • В XAML(как и в XML) символами-пробелами(whitespace) считаются пробел(Unicode 0020), символ перевода строки (\n-Unicode 000A) и символ табуляции (\t - Unicode 0009). • По умолчанию синтаксический анализатор XAML сначала все символы-пробелы заменяет пробелами, а затем все подряд идущие пробелы заменяет одним пробелом. • Можно отказаться от обработки пробелов по умолчанию, указав атрибут xml:space="preserve”в элементах, для которых необходимо сохранить символы-пробелы. • В примере текст на кнопке button1 выводится в одну строку с одним пробелом между словами Test и Button, а текст на кнопке button2 в две строки с сохранением всех пробелов. <Button Height="23" Margin="34,0,31,80" Name="button1" VerticalAlignment="Bottom“>Test 
 Button</Button> <Button Height="41" Margin="34,0,31,8" Name="button2" VerticalAlignment="Bottom" xml:space="preserve"> Test 
 Button</Button>
Код(code-behind)и XAML • Обычно WPF-приложение содержит как разметку( XAML код), так и код C# (code-behind). • Обычно XAML полностью описывает интерфейс пользователя, а обработчики событий находятся в коде C#, их имена указываются в разметке как значения атрибутов. Обработчики вызываются на стадии выполнения, когда возникают события. • Соответствие разметки и кода C# устанавливается путем указания в корневом элементе XAML пространства имен и класса в атрибуте x:Class. • С объектами, которые создаются на основе определений в XAML, по умолчанию не связывается переменная. Для этой цели определен атрибут x:Name, с помощью которого с объектом можно связать переменную и использовать ее в коде C#. • Некоторые WPF-классы имеют свойство Name, которое можно использовать как эквивалент атрибута x:Name. • Класс XamlReader с методом Load дает возможность загрузить код XAML во время выполнения. В результате компиляции будет создано дерево объектов, которое можно использовать как значение свойства ранее созданного в приложении объекта. Это возможно только в full-trust приложениях.
Атрибуты XAML и значения свойств объектов WPF • Значением атрибута XAML должна быть строка символов, заключенная в двойные кавычки. • Значение обрабатывается XAML-процессором и определяется типом свойства CLR. • для примитивных типов используется принятое по умолчанию преобразование типа string к данному типу; • для свойства, которое имеет тип перечисление(enumeration), строка трактуется как имя элемента перечисления; • в остальных случаях значение атрибута должно быть обработано преобразователем типа (type converter). • Пример. В классе Button определены свойства public double Height { get; set; } public VerticalAlignment VerticalAlignment { get; set; } • В разметке свойству Height типа doubleприсвоено значение 23, а свойству VerticalAlignment, которое имеет тип перечисления VerticalAlignment, присвоено значение перечисления Bottom. <Button Height="23" HorizontalAlignment="Center" Margin="13,0,0,56" Name="button1" VerticalAlignment="Bottom" Width="75">Get</Button>
Преобразователи типов (TypeConverters) • Преобразователь типа (type converter) определяется либо для конкретного свойства класса CLR, которому присваивается значение, либо для типа этого свойства. • Преобразователь принимает строку и как результат возвращает объект типа, который имеет свойство CLR. <Button Height="23" HorizontalAlignment="Center" Margin="13,0,0,56" Name="button1" VerticalAlignment="Bottom" Width="75">Get</Button> • Свойство Marginкласса Buttonимеет тип Thickness. public Thickness Margin { get; set; } • Со структурой Thicknessсвязан преобразователь ThicknessConverter, который преобразует строку к типу Thickness.
Преобразователи типов(TypeConverters) в WPF • Преобразователь типа связывается с типом или конкретными свойствами типа с помощью атрибута CLR TypeConverterAttribute, которому передается как параметр имя типа, который будет использоваться как преобразователь. • Так структура Thickness объявлена с атрибутом CLR TypeConverterAttribute, в котором в качестве преобразователя указан класс ThicknessConverter. [TypeConverterAttribute(typeof(ThicknessConverter))] public struct Thickness : IEquatable<Thickness> • Класс-преобразователь типа должен быть производным от класса TypeConverterи может переопределять методы, выполняющие преобразования, ( например, ConvertTo и ConvertFrom) и булевские свойства CanConvertTo и CanConvertFrom , предоставляющие информациею о том, возможны ли преобразования. public Object ConvertFrom( Object value ); public boolCanConvertTo( Type destinationType ); public boolCanConvertFrom( Type sourceType ); public boolCanConvertTo( Type destinationType );
Элемент-свойство (property element) • Для установки значений свойств, которые являются ссылками на объекты ( возможно имеющие свой набор свойств) может использоваться синтаксис элемент-свойство (property element). • Синтаксисэлемента-свойство: <TypeName.Property> content </TypeName.Property> • Обычно content – это объект, который принимается как значение свойства. • В примере синтаксис элемент-свойство используется для установки значения свойства ContextMenuкласса ListBox. public ContextMenu ContextMenu { get; set; } • В разметке как значение свойства ContextMenuиспользуется элемент <ContextMenu>. <ListBox Margin="44,54,48,60" Name="listBox1"> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="_File"/> <MenuItem Header="_Edit"/> </ContextMenu> </ListBox.ContextMenu> </ListBox>
Синтаксис элемент-свойство для коллекций • Для свойства, которое является коллекцией, тип коллекции в разметке не указывается . Элементы коллекции размещаются как один или несколько дочерних элементов. • В процессе загрузки каждый элемент инициализируется (конструктором без параметров) и добавляется в коллекцию с помощью метода Add. • XAML–процессор для WPF поддерживает коллекции, реализующие интерфейсы IListи IDictionary. • Расширения XAML поддерживают работу с массивами. • В примере свойствоItemsкласса ContextMenu, представляющее собой коллекцию ItemCollectionэлементов типаMenuItem,инициализируется с использованием синтаксиса элемент-свойство для коллекций. <ListBox Margin="44,54,48,60" Name="listBox1"> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="_File"/> <MenuItem Header="_Edit"/> </ContextMenu> </ListBox.ContextMenu> </ListBox>
Обработчики событий • Обычно WPF-приложение содержит как XAML код, так и код на C#( code-behind). • Обработчики событий обычно находятся в коде C#, их имена указываются в разметке как значения атрибутов. • В примере в разметке с событием Closingдляокна связан обработчик Window_Closing, а с событиемClickдля кнопки - обработчик button1_Click. <Window x:Class="Wpf_Sample1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" Closing="Window_Closing"> <Grid> <Button Height="23" HorizontalAlignment="Center" Margin="13,0,0,56" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click">Get</Button> </Grid> </Window> • Обработчики должны иметь тип, отвечающий событию. private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { MessageBoxResult res = MessageBox.Show("Закрыть окно?", "", MessageBoxButton.YesNo); if (res == MessageBoxResult.No) e.Cancel = true; } private void button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show ("Pressed button Get“); }
Расширения языка разметки (Markup extentions) • По умолчанию XAML-процессор интерпретирует значения атрибутов как литеральные строки и выполняет преобразование строк в объекты с помощью преобразователей типов. • Расширения языка разметки (markup extentions) позволяют выполнить более сложную инициализацию: • использовать ссылку на ранее созданный или статический объект; • указать в конструкторе объекта значения параметров, отличные от значений по умолчанию; • отложить обработкузначенийдо времени выполнения, передав ее классу (backing class). • Расширения разметки заключаются в фигурные скобки. • Наиболее часто используемые расширения языка разметки в WPF - Binding, StaticResource и DynamicResource.
Расширения языка разметки. Пример • В следующем примере контекстное меню определено как ресурс с ключом MyContextMenu_1 и затем используется как значение для свойства ContextMenu элемента ListBox <Window x:Class="WPF_ContextMenu.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="381" Width="484" Loaded="Window_Loaded"> <Window.Resources> <ContextMenu x:Key="MyContextMenu_1"> <MenuItem Header="Add" Click="Add_MenuItem_Click"></MenuItem> <MenuItem Header="New" Command="ApplicationCommands.New"></MenuItem> </ContextMenu> </Window.Resources> <Grid > <ListBox Margin="19,18,208,0" Name="listBox1" Height="107" VerticalAlignment="Top" ContextMenu="{StaticResource MyContextMenu_1}"/> </Grid> </Window>
Контентный синтаксис (Content Syntax)в XAML • Контентный синтаксис XAML допустим только для классов CLR, имеющих атрибут ContentPropertyAttribute в объявлении. • В параметре атрибута ContentPropertyAttributeуказывается имя свойства класса CLR, которое XAML-процессор трактует как содержимое (content) для данного класса ( включая производные классы). • Например, класс Buttonимеет атрибут ContentPropertyAttribute, унаследованный от базового класса ContentControl. [ContentPropertyAttribute("Content")] public class ContentControl : Control, IAddChild • Класс ListBoxимеет атрибут ContentPropertyAttribute, унаследованный от базового класса ItemsControl. [ContentPropertyAttribute("Items")] public class ItemsControl : Control, IAddChild • XAML-процессор любой дочерний элемент или внутренний текст между открывающим и закрывающим тэгом элемента трактует как содержимое элемента. Исключение составляют тэги элементов-свойств, которые обрабатываются в первую очередь и не рассматриваются как содержимое элемента. • Контентное свойство объекта имеет конкретный тип. Контентным типом может быть тип-коллекция, но в любом случае содержимое -это единственный объект.
Контентный синтаксис в XAML. Пример • Значение контентного свойства XAML дожно быть непрерывным, то есть должно находиться целиком до или целиком после любого другого элемента-свойства. <ListBox Margin="20,54,19,0" Name="listBox1" Height="64" VerticalAlignment="Top"> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="_File"/> <MenuItem Header="_Edit"/> </ContextMenu> </ListBox.ContextMenu> <ListBoxItem>Green</ListBoxItem> <ListBoxItem>White</ListBoxItem> <ListBoxItem>Red</ListBoxItem> </ListBox> • В примере сначала инициализруется свойство ContextMenuобъектаListBox. В классе ContextMenuконтентным является свойствоItems, представляющее собой коллекцию. • Затем инициализируетяконтентное свойствоItemsклассаListBox, также представляющее собой коллекцию. • Каждый элемент коллекции является объектомтипа ListBoxItem, который наследует контентное свойство Contentот базового класса ContentControl.