- •Приложение и класс Application
- •. Компоновка (Layout)
- •Элементы управления Обзор элементов управления
- •Visibility
- •Элементы управления содержимым
- •Специальные контейнеры
- •Декораторы
- •ViewBox
- •Текстовые элементы управления
- •Элементы управления списками
- •Элементы, основанные на диапазонах значений (Range Controls)
- •Элементы для работ с датами
- •Остальные элементы управления
- •Модель событий в wpf
XAML
XAML (eXtensible Application Markup Language) - язык разметки, используемый для создания пользовательского интерфейса декларативным путем. Это, наверное, одно из главных отличий от технологии WinForms.
Создадим первое приложение
Откроем Visual Studio и создадим проект WPF Application. Дадим ему любое имя. В результате увидим стандартное окно Visual Studio, за исключением одной детали.

Эта деталь называется окно XAML. Тут также, как и в WinForms, можно перетаскивать контролы мышкой из вкладки Toolbar (Панели инструментов). А можно напечатать разметку контролов в окне XAML. Вставим между строками <Grid> и </Grid> следующий код, чтобы получилось изображение, привиденное выше:
?
|
1 2 3 4 5 6 7 8 9 |
<Button x:Name="Button1" Background="Azure" Width="150" Height="50" Margin="120,41,54,220"> <Button.RenderTransform> <RotateTransform Angle="45" /> </Button.RenderTransform> <Canvas> <Ellipse Fill="Red" Width="20" Height="20" Stroke="Black" Margin="-100 -10 0 0"></Ellipse> <TextBlock Background="Azure" Margin="-35 -10 0 0" Width="80" FontSize="15" FontStretch="Expanded">Record</TextBlock> </Canvas> </Button> |
Запускаем на выполнение кнопкой F5. В итоге у нас получилась наклоненная на 45 градусов кнопка. Если бы мы перетащили из вкладки Toolbox кнопку и ряд контролов на форму,то автоматически создалась бы разметка в XAML, соответствующая данным контролам.
Таким образом, несложно заметить, что XAML напоминает html - все контролы прописываются в угловых скобках, далее идут названия их свойств или атрибутов и в кавычках - значения этих свойств. Но возможно некоторые затруднения могут возникнуть, если взглянув на шапку разметки XAML, где мы видим следующий код:
?
|
1 2 3 4 |
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="350"> |
Вторая и третья строчки представляют собой пространства имен, подключаемые в проект по умолчанию. xmlns представляет специальный атрибут для определения пространства имен. http://schemas.microsoft.com/winfx/2006/xaml/presentation заключает описание и определение большинства элементов управления. Так как является пространством имен по умолчанию, то объявляется без всяких префиксов. http://schemas.microsoft.com/winfx/2006/xaml - это пространство имен, включающее некоторые свойства XAML, например свойство Name или Key. Используется с префиксом x, это значит, что те свойства элементов, которые заключены в этом пространстве имен, будут использоваться с префиксом x - x:Name или x:Key. Это же пространство имен используется уже в первой строчке x:Class="MainWindow" - здесь создается новый класс MainWindow и соответствующий ему файл кода, куда будет прописываться логика для данного окна приложения.
Эти пространства имен не эквивалентны тем пространствам имен, которые подключаются при помощи директивы Imports(vb.net) или using(c#). Так, например, http://schemas.microsoft.com/winfx/2006/xaml/presentation подключает в проект такие пространства имен как System.Windows, System.Windows.Controls, System.Windows.Media и ряд других. (В проектах иногда может встретиться вместо данного пространства имен немного другие - http://schemas.microsoft.com/netfx/2006/xaml и http://schemas.microsoft.com/netfx/2007/xaml/presentation - они эквивалентны, только если первое представляет .NET 3.0, то два других - .NET 3.5 и .NET 4.0 соответственно.) Все подключаемые пространства имен должны идти в начале. Затем идут уже обычные объявления свойств и их значений - Title="MainWindow" Height="350" Width="350". Здесь задается заголовок окна, ширина и высота.
Кроме обычных свойств иногда требуется прописать более сложные свойства, у которых более сложная логика. чем простое присваивание определенному значению. Именно так произошло со свойством RenderTransform класса Button в вышеприведенном примере с повернутой кнопкой. Так, для определения свойства RenderTransform потребовался класс свойство Angle класса RotateTransform
Кроме свойств в XAML можно прописывать обработчики для соответствующих событий. Например, <Button x:Name="Button1" Background="Azure" Width="150" Height="50" Margin="120,41,54,220" Click="Button1_Click">
Здесь мы соединяем событие Click с обработчиком событий Button1_Click, который прописан в файле кода. Обработчик может выглядеть примерно так:
?
|
1 2 3 4 |
private void Button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Привет мир"); } |
Мы можем также импортировать любые другие доступные нам пространства имен платформы .NET. Общий синтаксис задания пространств имен таков:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
сначала идет спецификатор xmlns, затем - префикс, на который будет отображаться пространство имен (любой не занятый префикс), после clr-namespace идет пространство имен, а после assembly - сборка, в которой оно находится.
Затем уже в xaml-коде можно обращаться к классам из подключенных пространств имен по префиксу, например sys:String - в данном случае sys - префикс для пространства System, а именно там находится класс String
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<Window x:Class="Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:col="clr-namespace:System.Collections;assembly=mscorlib" Title="Window1" Height="200" Width="300" Loaded="Window_Loaded"> <Grid> <Grid.Resources> <col:ArrayList x:Key="array" x:Name="arrList"> <sys:String>Понедельник</sys:String> <sys:String>Вторник</sys:String> <sys:String>Среда</sys:String> <sys:String>Четверг</sys:String> <sys:String>Пятница</sys:String> <sys:String>Суббота</sys:String> <sys:String>Воскресенье</sys:String> </col:ArrayList> </Grid.Resources> </Grid> </Window> |
Можно также подключить и использовать в xaml-коде все классы, определенные в приложении. Пространство имен текущего приложения подключается так:
xmlns:local="clr-namespace:Имя_текущего_приложения
Кроме того, XAML сближает с html возможность выполнения в браузере. В первую очередь, это относится к Silverlight-приложениям. Однако xaml-файлы обычных приложений wpf также можно при некоторых условиях просмотреть в браузере. Так, немного изменив наш файл MainWindow.xaml, можно открыть его в браузере Internet Explorer 9 и получить следующую картинку

Приложение и класс Application
В предыдущем разделе продемонстрирован пример простого приложения. Однако само приложение начинается не с класса Window, а с класса Application. По умолчанию при создании проекта WPF создается файл App.xaml и класс связанного кода App.xaml.cs. Файл App.xaml выглядит примерно так:
?
|
1 2 3 4 5 6 7 8 |
<Application x:Class="WpfApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose"> <Application.Resources>
</Application.Resources> </Application> |
Здесь также указываются класс связанного кода и импортируемые пространства имен. Кроме того, в разметке приложения должно быть определено свойство StartupUri. Оно указывает на окно или страницу (в случае браузерного приложения), с которого начинается выполнение приложения. Добавив в приложение несколько окон, тут мы можем указать то, которое буте запускаться при вызове приложения. Также здесь объявлены два свойства - ShutdownMode и Resources.
Свойство ShutdownMode указывает на способ выхода из приложения и может принимать одно из следующих значений:
|
Значение |
Описание |
|
OnMainWindowClose |
Приложение работает, пока открыто главное окно |
|
OnLastWindowClose |
Приложение работает, пока открыто хотя бы одно окно |
|
OnExplicitShutdown |
Приложение работает, пока не будет явно вызвано Application.Shutdown() |
Свойство Resources указывает на коллекцию ресурсов, общих для всего приложения. Еще одно свойство MainWindow указывает на главное окно приложения.
Кроме того класс Application поддерживает ряд событий, с помощью которых можно задать некоторую общую логику приложения в файле отделенного кода App.xaml.cs.
Событие Startup
Происходит после вызова метода Application.Run() и перед показом главного окна. Сначала определим событие в разметке XAML в файле App.xaml:
?
|
1 2 3 4 5 6 7 8 |
<Application x:Class="WpfApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" Startup="App_Startup"> <Application.Resources>
</Application.Resources> </Application> |
Затем в файле связанного кода App.xaml.cs пропишем обработчик события:
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class App : Application { //Запуск одной копии приложения System.Threading.Mutex mut; private void App_Startup(object sender, StartupEventArgs e) { bool createdNew; string mutName = "Приложение"; mut = new System.Threading.Mutex(true, mutName, out createdNew); if (!createdNew) { Shutdown(); }
} } |
В результате при запуске каждой новой копии данного приложение обработчик события будет определять, запущена ли уже приложение, и если оно запущено, то данная копия завершит свою работу.
События Activated и Deactivated
Событие Activated происходит, когда активизируется одно из окон приложения. Синтаксис события:
?
|
1 2 |
private void Application_Activated(object sender, EventArgs e) {} |
Соответственно событие Deactivated происходит при потере окном фокуса
Событие SessionEnding
Происходит при завершении сеанса Windows при перезагрузке, выключении или выходе из системы текущего пользователя. Синтаксис события:
?
|
1 2 3 4 5 6 7 |
private void Application_SessionEnding(object sender, SessionEndingCancelEventArgs e) { //Вывод причины завершения сеанса MessageBox.Show(e.ReasonSessionEnding.ToString()); //Отмена завершения сеанса e.Cancel = true; } |
Событие DispatcherUnhandledException
Происходит при возникновении необработанных исключений. Синтаксис события:
?
|
1 2 3 4 |
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show(e.Exception.ToString()); } |
Событие Exit
Происходит при выходе из приложения Это может быть закрытие главного или последнего окна, метод Application.Shutdown() или завершение сеанса. Синтаксис события:
?
|
1 2 |
private void Application_Exit(object sender, ExitEventArgs e) {} |
Событие LoadCompleted
Происходит при завершении загрузки приложения. Синтаксис события:
?
|
1 2 |
private void Application_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e) {} |
Обращение к текущему приложению
Мы можем обратиться к текущему приложению из любой точки данного приложения. Это можно сделать с помощью свойства Current, определенном в классе Application. Так, изменим код нажатия кнопки на следующий:
?
|
1 2 3 4 5 6 7 |
private void Button1_Click(object sender, RoutedEventArgs e) { foreach (Window window in Application.Current.Windows) { MessageBox.Show(window.ToString()); } } |
Таким образом, при нажатии на кнопку мы получим одно или несколько сообщений с именами всех окон данного приложения
