Файлы к данному курсу Вы можете скачать здесь.
Цель лекции: показать читателям предпосылки возникновения модели декларативного программирования XAML, разобрать основополагающие элементы XAML (контейнеры, элементы управления, службы документов, графические примитивы), а так же кратко познакомить с текущей поддержкой языка XAML, и моделью программирования.
Человечество проделало огромный путь в технологиях создания пользовательского интерфейса. Когда-то, на заре компьютерной эры, единственный интерфейс пользователя составляла колода перфокарт, которые программист загружал в компьютер, и бумажная лента, которую компьютер ему выдавал. Первым революционным шагом стало появление консоли, что автоматически (хотя и далеко не сразу) привело к смене парадигмы общения компьютера и пользователя с пакетной обработки к интерактивной. Довольно долго консоли были текстовыми, и пользовательский интерфейс, в основном, сводился к вопросам и ответам. Однако и в консоли со временем появились довольно богатые интерфейсы, использовавшие возможности псевдографики.
В то же время становится популярной Windows, что в очередной раз меняет подходы к созданию интерфейсов. Windows предложила набор стандартных элементов управления (или, общепринятое, "контролов"), а также API для работы с ними. Это позволило приложениям выглядеть одинаково с системными, не говоря уже о существенном облегчении в программировании UI, т.к. большую часть труда взяла на себя система.
Поначалу набор контролов был недостаточен, а API вызывало много нареканий, но с развитием Windows положение вещей улучшалось. Кроме того, появилось много альтернатив низкоуровневому API Windows. В частности, можно упомянуть "родные" Microsoft’овские технологии
Параллельно с появлением и развитием технологий, подобных
Наконец, надо упомянуть и третью ветвь развития UI, появившуюся примерно в то же время – UI сначала веб-страниц, потом и веб-приложений. Поначалу это был чистый HTML, потом как грибы после дождя стали появляться многочисленные технологии вроде Java-апплетов, flash-приложений и т.п. Наконец, с выходом Microsoft.NET появились технологии Windows Forms и ASP.NET.
Итак, с точки зрения UI у нас существует три разных типа приложений, каждый из которых имеет свой набор технологий для реализации. И одной из предпосылок создания WPF является идея интеграции подобных технологий в одной. Идея интеграции всего со всем вообще является доминирующей последние годы. Кроме того, текущей графической платформе Windows уже 20 лет. Это прекрасно, но, учитывая ошеломительное развитие аппаратных графических средств (видеокарт и разнообразных
Наконец, еще одной предпосылкой появления WPF стала неудовлетворенность текущей схемой общения дизайнера и разработчика при создании UI. Это мы обсудим чуть позже в данной лекции.
WPF –
Надо отметить, что WPF – это не только диалоги, картинки и видео. Кроме прочего, WPF включает в себя также синтез и распознавание речи. Более полный список того, что поддерживается WPF:
Одной из идей WPF является то, что программирование UI хочется сделать как можно более декларативным. В самом деле, почему размеры и расположение элементов управления, реакцию на всякие события и т.п. надо реализовывать в коде, если эта информация известна заранее? Эти соображения привели разработчиков WPF к идее использовать XML для описания пользовательского интерфейса. Стандарт называется XAML (eXtensible Application Markup Language), и файл на нем выглядит примерно так:
<Button Width="200px" Click="onHelloClick">
Hello, XAML!
<Button.Background>
LightBlue
</Button.Background>
</Button>
Вы могли бы подумать, что вам предлагается всего лишь описать раскладку элементов управления и обработчики событий, но это не так. Например, вы можете описать различные трансформации ваших элементов управления, их анимацию и т.п.
Идея использовать XML для описания UI не нова. Достаточно популярен язык разметки XUL (XML User Interface Language). XUL является частью среды разработки кросс-платформенных интерфейсов, известной как XPFE. Это полнофункциональный язык разметки, на объекты приложений, такие как окна, метки и кнопки.
C помощью XAML описывается, прежде всего, пользовательский интерфейс. Логика приложения по-прежнему управляется процедурным кодом (С#, VB и т.д.).
XAML может использоваться как для браузер-базированных приложений, так и для локальных настольных приложений. Немаловажной деталью является легкость XAML для локализации UI. Если раньше для этих целей использовали специальные механизмы вроде таблицы строк, загрузки строк из ini-файлов, ресурсные dll или же специальных утилит "вытаскивания" строк, то с появлением XAML, хранящего все строчки UI в текстовом виде, локализация значительно упрощается.
Наконец, формат XAML, основанный на XML, очень легко генерировать программно, что открывает более широкие возможности для третьесторонних разработчиков, реализующих различные инструменты работы с UI, по сравнению с текущей ситуацией, когда приходится генерировать UI в закрытых проприетарных форматах.
Интерфейс пользователя WPF-приложения задается XAML. C XAML может быть связан скомпилированный code-behind код (что может вызвать легкое ощущение дежавю у знакомых с моделью ASP.NET). Например, если страница вашего приложения описывается файлом page.xaml, то code-behind, как правило, будет храниться в page.xaml.cs. Codebehind может содержать реакцию на различные события, генерируемые пользовательским интерфейсом (такие как нажатие клавиши мыши или "наезд" указателя мыши на элемент управления). Одной из светлых целей такого разделения является написание одного кода для всех типов приложений (то есть, ваш код можно было бы скомпилировать и как настольное приложение, и как приложение, просматриваемое с помощью браузера, и как smart client-приложение).
Т.к. XAML – это "нормальный" XML, то он подчиняется всем правилам wellformed XML, в частности, содержит ровно одну корневую вершину и является деревом. На вершине иерархии находится один из контейнерных объектов. Внутри этих объектов располагаются знакомые нам элементы управления и другие контейнеры. Набор элементов управления, без сюрпризов, очень похож на "старый добрый" набор контролов Win32. Это кнопки, меню, текст, картинки и т.п. Но на самом деле каждый тег XAML соответствует классу модели, который, в свою очередь, имеет набор свойств, методов и событий. В соответствие с этими членами класса вы можете настраивать ваш XAML-код. Во время исполнения именно экземпляры этих классов создаются рантаймом для того, чтобы отобразить то, что вы указали в XAML, – очень похоже на ASP.NET и его серверные контролы.
Основное деление элементов XAML таково:
С помощью панелей вы можете располагать содержащиеся внутри них элементы. Среди стандартных панелей есть Canvas (дочерние элементы размещаются с использованием относительных координат), DockPanel (панель, в которой дочерние элементы стыкуются), FlowPanel (напоминает джавский FlowLayout, где элементы выводятся в ряд друг за другом), GridPanel (табличная организация сыновей) и некоторые другие. Естественно, вы можете определять свои типы панелей. Пример панели:
<DockPanel xmlns="http://schemas.microsoft.com/2003/xaml>
<Button DockPanel.Dock="Left" Width="50px" Height="30px">One</Button>
<Button DockPanel.Dock="Left" Width="50px" Height="30px">Two</Button>
<Button DockPanel.Dock="Left" Width="70px" Height="30px">Three</Button>
</DockPanel>
На этой панели будет создано три кнопки, состыкованные друг с другом по горизонтали. Обратите внимание на указание соответствующего пространства имен в элементе верхнего уровня.
Элементы управления, как уже было сказано, во многом уже знакомы программистам Win32 и WinForms. Все они унаследованы от типа Control, среди них есть старые добрые комбобоксы, листбоксы, меню, скроллбары, слайдеры, и т.п., а есть и новые контролы наподобие RadioButtonList. XAML однако же дает вам невероятную гибкость в настройке свойств этих контролов (то, чего ранее можно было добиться только нелегким трудом ручной отрисовки owner draw). Так, например, чтобы нарисовать кнопку с изображением (что, правда, стало несложно и во второй версии WinForms), в WPF надо всего лишь написать
<Button>
<Image Source="myphoto.jpg">
</Button>
Вы можете задавать различные цвета, кисти, градиентные заливки и даже сделать кнопку с чек-боксом на ней!
С ними все понятно, набор весьма стандартен – Ellipse, Line, Rectangle, Path, Polygon,
Графические примитивы не имеют дочерних элементов и обычно содержатся внутри панели Canvas, например:
<Canvas xmlns = "http://schemas.microsoft.com/2003/xaml">
<Line X1 = "0" Y1 = "0" X2 = "100" Y2 = "200" Stroke = "red" />
</Canvas>
нарисует обычную линию красного цвета из 0,0 в 100, 200 (в локальных координатах панели).
В то время как традиционная веб-страница имеет непрерывное представление, отображая весь контент в одном едином блоке, сервисы управления документами предоставляют вам удобные возможности разбивать контент на страницы, масштабировать содержимое, адаптировать документы под специфические особенности дисплея пользователя и т.д. Еще один шаг, приближающий веб-интерфейс к привычному интерфейсу настольных приложений.
С помощью XAML вы можете определить различные преобразования (трансформации) над элементами интерфейса. Среди стандартных преобразований есть:
Например, вы можете повернуть обычную надпись с помощью единственного преобразования:
<Canvas xmlns = "http://schemas.microsoft.com/2003/xaml/">
<TransformDecorator>
<TransformDecorator.Transform>
<RotateTransform Angle="45"/>
</TransformDecorator.Transform>
<Text>Hello!</Text>
</TransformDecorator>
</Canvas>
или отобразить список (ListBox) с помощью нескольких преобразований, объединенных TransformCollection, так, что он будет растянут и перевернут:
<Canvas xmlns="http://schemas.microsoft.com/2003/xaml">
<TransformDecorator>
<TransformCollection>
<RotateTransform Angle="100"/>
<ScaleTransform ScaleX="2", ScaleY="1"/>
</TransformCollection>
<ListBox>
<ListBoxItem> One </ListBoxItem>
<ListBoxItem> Two </ListBoxItem>
<ListBoxItem> Three </ListBoxItem>
</ListBox>
</TransformDecorator>
</Canvas>
Кроме преобразований XAML предлагает вам также возможности анимации (нечто похожее на преобразования, но что можно повторять и применять многократно). Например, вы можете сделать кнопку, которая при наведении на нее мышки будет постепенно растягиваться до некоторых пределов (не скачком) и также постепенно сужаться после того, как мышка будет отведена. Анимировать можно все свойства элементов управления, что позволяет вам создавать сколь угодно изощренные эффекты анимации. Правда сказать, создавать эти эффекты руками – не самое благодарное занятие. Например, взгляните на доступные для скачивания примеры XAML на сайте http://xamlshare.com. Конечно же, для создания более-менее сложных UI лучше использовать продукты семейства Expression (рассматриваемые ниже).
Важный вопрос – каким образом можно управлять всем этим великолепием с целью улучшения повторного использования внешнего вида элементов. Тут 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 в IDE и в графических редакторах. Таким средства есть:
Семейство Expression-редакторов работает как с векторной графикой (напомним, что движок WPF – векторный), так и с растровыми изображениями.
Язык 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.
| Пространство имен 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" "internal" и т.д.) (используется только при компиляции разметки) | <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 | Задает имя элемента для ссылки на него в программе (обычно используется, когда у элемента нет | <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: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) — общее наименование целого набора базовых функций
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 язык разметки для декларативного
XML (англ. eXtensible Markup Language — расширяемый язык разметки) — рекомендованный Консорциумом Всемирной паутины язык разметки, фактически представляющий собой свод общих синтаксических правил. XML — текстовый формат, предназначенный для хранения структурированных данных (взамен существующих файлов баз данных), для обмена информацией между программами, а также для создания на его основе более специализированных языков разметки (например, XHTML).
В данной теме были рассмотрены основные синтаксические конструкции языка XAML и приведены простые примеры их реализации. Проектирование WPF-приложений требует от разработчика понимания структуры и содержания XAML-документа, описывающего интерфейс создаваемой системы. В последующих темах курса будут рассматриваться различные аспекты построения WPF- и Silverlight-приложений и необходимым условием эффективной работы создателя таких систем является знание основ языка XAML.
Вопросы:
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.