Освоить основные приемы разработки WPF-приложений на основе
Как правило, корпоративное приложение представляет собой программу, реализующую определенную бизнес-задачу (бизнес-функцию). Приложение должно взаимодействовать с данными, которые располагаются в базе данных информационной системы. Архитектура приложения обычно включает слой представления, бизнес-логики и данных. Функциональность каждого слоя приложения во многом определяется предметной областью информационной системы, но имеются и общие, основополагающие функции, которые присущи практически любому корпоративному приложению. Так в приложении необходимо разработать слой представления, который обеспечит интерфейс пользователя с системой. Интерфейс может быть создан с использованием Windows окон и страниц WPF, которые наполняются различными визуальными элементами контроля. Элементы контроля должны поддерживать визуальное представление функциональности системы для пользователя, проводить верификацию вводимых данных и взаимодействовать с бизнес-классами.
Слой бизнес-логики приложения должен обеспечивать основную функциональность приложения: формировать бизнес-классы, реализовывать алгоритмы обработки данных, обеспечивать соединение с данными и их кэширование. Реализация данного слоя приложения может быть построена на базе классов, реализующих бизнес-логику, методами классов интерфейсных элементов или методами классов модели данных. Слой данных должен обеспечить взаимодействие приложения с данными
Для изучения вопросов проектирования корпоративных приложений рассмотрим основные подходы при разработке отдельной функции информационной системы, которая обеспечивает обработку данных по сотрудникам компании. Для учебного примера используется база данных TitlePresonal с небольшим набором таблиц и полей, а функциональность приложения предполагает обеспечение ввода, корректировки и удаление данных о сотрудниках компании. Разрабатываемое приложение должно обеспечивать хранение и обработку следующих данных по сотрудникам компании: фамилия; имя; отчество; должность; дата рождения; телефон; адрес электронной почты.
Функции приложения:
Для разработки приложения необходимо создать WPF-проект (рис 4.1). В окне " ), выбрать шаблоны Windows (2 – на рис 4.1), а среди имеющихся шаблонов задать Приложение WPF и в поле " Имя " ввести имя проекта WpfApplProject.
После нажатия кнопки " ОК " будет сформирован шаблон проекта. При этом инструментальная система сгенерирует следующий XAML-документ:
<Window x:Class="WpfApplProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
(рис 4.1) Окно создания проектаДизайнер проекта приведен на рис 4.2.
(рис 4.2) Окно дизайнера проектаВ приведенном XAML-документе имеется один элемент верхнего уровня <Window>. Дескриптор </Window> завершает весь документ. В XAML-документе приведено имя класса MainWindow
x:Class="WpfApplProject.MainWindow
два пространства имен
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
и три свойства:
Title="MainWindow" Height="350" Width="525"
Каждый атрибут соответствует определенному свойству класса .
(рис 4.3) Окно MainWindow проектаКогда выполняется компиляция приложения, XAML-файл, который определяет пользовательский интерфейс ( MainWindow.xaml ), транслируется в объявление типа CLR , которое объединяется с логикой приложения из файла класса отдельного кода ( MainWindow.xaml.cs ).
Метод InitializeComponent() генерируется во время компиляции приложения и в исходном коде не присутствует.
Для программного управления элементами управления, описанными в XAML-документе, необходимо задать XAML атрибут Name. Так для задания имени элементу Grid необходимо записать следующую разметку:
<Grid Name="grid">
</Grid>
В последнее время разработчики корпоративных приложений начали осознавать преимущества технологий веб-дизайна, которые базируются на качественном дизайне, четком и понятном интерфейсе. Технология WPF позволяет создавать
Страницы можно размещать внутри окон и внутри других страниц. В WPF при создании страничных приложений контейнером наивысшего уровня могут быть следующие объекты:
Для вставки страницы внутрь окна будем использовать класс ). Автоматически будет сгенерирован экземпляр класса ).

(рис 4.5) Выбор класса Frame в панели инструментов(рис 4.4) Фрейм с фиксированными границамиВ XAML-документ проекта будет добавлена следующая строка:
<Frame Height="100" HorizontalAlignment="Left" Name="frame1" VerticalAlignment="Top" Width="200" />
С учетом того, что создается страничное приложение размеры фрейма не нужно фиксировать, поэтому изменим описание свойств фрейма:
<Frame Name="frame1" Margin="3" />
В результате фрейм заполнит всё окно (рис 4.6):
(рис 4.6) Фрейм, заполняющий всё окноСозданный фрейм необходим для размещения в нем страницы WPF-приложения. Класс Page допускает наличие только одного вложенного элемента. Он не является элементом управления содержимым и наследуется от класса FrameworkElement. Класс Page имеет небольшой набор дополнительных свойств, которые позволяют настраивать его внешний вид, взаимодействовать с контейнером и использовать навигацию. Для перехода на другую страницу необходимо использовать навигацию.
Класс Page имеет следующие свойства:
Добавим в проект начальную страницу. Для этого в ), а в раскрывающемся меню пункт ).
В окне ).

(рис 4.8) Меню создания страницы(рис 4.7) Окно Добавления нового элементаВ дизайнере проекта сгенерируется страница ).
(рис 4.9) Дизайнер страницы PageMain.xamlВ сгенерированной странице в качестве контейнера верхнего уровня используется Grid. Заменим Grid на контейнер StackPanel.
Объект StackPanel имеет свойство Background, которое предоставляет кисть для рисования фоновой области элемента. Данное свойство является сложным, т.е. должно задаваться в следующем виде:
<StackPanel.Background> ... </StackPanel.Background>
Классы кистей наследуются от класса System.Windows.Media.Brush и обеспечивают различные эффекты при заполнении фона, переднего плана или границ элементов. Некоторые классы кистей приведены ниже:
Создадим градиентную заливку созданной страницы. Для определения градиентной заливки необходимо создать объект LinearGradientBrush. Далее необходимо заполнить свойство LinearGradientBrush.GradientStops коллекцией объектов GradientStop. Каждый объект GradientStop имеет свойства Offset и Color, значение которых задаются в соответствии с синтаксисом " свойство - атрибут ". Свойство Offset может принимать значение от 0 до 1, определяя области заполнения градиентом от одного цвета к другому.
Далее приведен фрагмент XAML-документа для определения градиентной заливки страницы.
<StackPanel.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="#FF87A0DE"/>
<GradientStop Offset="0.50" Color="Azure"/>
<GradientStop Offset="1.00" Color="#FF009CFF"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</StackPanel.Background>
Добавим в страницу текстовую строку "Система внутреннего учета инвестиционной компании".
<TextBlock Margin="25,30,25, 5" FontSize="20">
Система внутреннего учета инвестиционной компании
</TextBlock>
Подключим созданную страницу к фрейму. Для этого в разметке фрейма необходимо указать источник его заполнения Source, а также определим свойства Foreground, BorderBrush и Background.
<Frame Name="frame1" Margin="3" Source="PageMain.xaml" Foreground="#FFE4D8D8" BorderBrush="#FFF7F3F3" Background="#FFB3D9E5"/>
Главная страница приложения в дизайнере представлена на рис 4.10.
(рис 4.10) Главная страница WPF-приложения в дизайнереИзменим свойство .
(рис 4.11) Главная страница WPF-приложенияКонтейнером верхнего уровня главной страницы приложения является StackPanel. Для данной панели свойству Background, которое определяет кисть для рисования фоновой области, установлено сложное значение, определяющее градиентную заливку. С учетом того, что в приложении предполагается использовать аналогичную градиентную кисть и для других страниц, то целесообразным является сформировать значение для данной кисти в виде ресурса, разместив его на уровне приложения.
<Application.Resources>
<LinearGradientBrush x:Key="BackgroundWindowResource">
<GradientStop Offset="0.00" Color="#FF87A0DE"/>
<GradientStop Offset="0.50" Color="Azure"/>
<GradientStop Offset="1.00" Color="#FF009CFF"/>
</LinearGradientBrush>
</Application.Resources>
Сформированный ресурс для градиентной кисти имеет ключ BackgroundWindowResource. Введение в XAML описание приложения ресурса требует провести изменение свойства Background панели StackPanel, использую расширения разметки и ссылку на статический ресурс BackgroundWindowResource.
<StackPanel Background="{StaticResource BackgroundWindowResource}">
. . .
</StackPanel>
На странице WPF-приложения можно размещать элементы пользовательского интерфейса (элементы управления) для обеспечения взаимодействия пользователя с бизнес-логикой системы.
Основная страница должна обеспечивать переход на другие страницы, обеспечивающие инферфейс для отдельных функций и выход из системы. Для перехода на другие страницы будем использовать гиперссылки. Гиперссылки позволяют пользователю перемещаться с одной страницы на другую. Элемент гиперссылки, соответствующий объекту класса Hyperlink, определяется следующей строкой:
<Hyperlink >Текст Гиперссылки</Hyperlink>
Класс Hyperlink имеет свойство NavigateUri. Данное свойство определяет на какую страницу будет переходить приложение при щелчке на соответствующей гиперссылке. Например, NavigateUri="Page2.xaml".
В WPF гиперссылки являются не отдельными, а внутристроковыми потоковыми элементами, которые должны размещаться внутри другого поддерживающего их элемента. Это можно сделать, например в элементе TextBlock, который для гиперссылки является контейнером.
На первой странице создадим следующие гиперссылки: Сотрудники, Клиенты, Договора, Ценные бумаги, Сделки и Справка. XAML-описание гиперссылки для страницы Сотрудники приведено ниже.
<TextBlock Margin="25,30,5, 5"> <Hyperlink NavigateUri="PageEmployee.xaml">Сотрудники</Hyperlink> </TextBlock>
Для реализации функциональности первого окна WPF-приложения осталось добавить кнопку выхода.
<Button Margin="25,15" Width="60" HorizontalAlignment="Left" Command="Close" >Выход</Button>
Результат компиляции и выполнения WPF-приложения приведен на рис 4.12.
(рис 4.12) Начальная страница WPF-приложения с гиперссылкамиПо условию учебного примера будем постепенно добавлять функциональность приложения в части обработки данных по сотрудникам компании.
Создадим страницу с именем PageEmployee. В качестве
<Page x:Class="WpfApplProject.PageEmployee"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600"
Title="PageEmployee">
<StackPanel Margin="3" Background="{StaticResource BackgroundWindowResource}">
</StackPanel>
Страница PageEmployee должна обеспечивать пользователю просмотр данных по сотрудникам, ввод данных по новому сотруднику, редактирование, поиск и удаление данных. Доступ пользователя к функциональности системы будем предоставлять через различные меню.
В WPF можно создать основное и контекстное меню. Кроме того, можно создать панель инструментов с кнопками, которые будут реализовывать функциональность, аналогичную пунктам меню.
Основное меню создается с помощью класса Menu, который представляет Windows элементы управления меню, позволяющие иерархически организовать элементы, связанные с командами и обработчиками событий. Меню формируют из объектов MenuItem (имя пункта меню) и Separator (разделитель). Класс MenuItem имеет свойство Header, которое определяет текст элемента меню. Данный класс может хранить коллекцию объектов MenuItem, которая соответствует подпунктам меню. Класс Separator отображает горизонтальную линию, разделяющую пункты меню. Добавим в StackPanel страницы PageEmployee XAML- описание меню, которое на верхнем уровне будет содержать два пункта Действие и Отчет. Пункт Действие включает подпункты Отменить, Создать, Редактировать, Сохранить, Найти и Удалить. Между пунктами Отменить, Создать и пунктами Найти, Удалить добавлены разделительные линии.
<Menu>
<MenuItem Header="Действие" >
<MenuItem Header="Отменить" ></MenuItem>
<Separator></Separator>
<MenuItem Header="Создать" ></MenuItem>
<MenuItem Header="Редактировать" ></MenuItem>
<MenuItem Header="Сохранить" ></MenuItem>
<MenuItem Header="Найти" />
<Separator></Separator>
<MenuItem Header="Удалить" ></MenuItem>
</MenuItem>
<MenuItem Header="Отчет"></MenuItem>
</Menu>
Запустим приложение и выберем ссылку ).
(рис 4.13) Главное меню страницы PageEmployeeПанель инструментов представляет специализированный контейнер для хранения коллекции элементов, обычно кнопок. Расположим в панели инструментов кнопки, функциональное назначение которых будет соответствовать подпунктам меню Действие, то есть Отменить, Создать, Редактировать, Сохранить, Найти и Удалить.
На лицевой стороне кнопок поместим графическое изображение соответствующего действия. Для этого добавим в файл проекта папку Images и в неё включим графические объекты, которые можно найти в библиотеке графических объектов Visual Studio (папка VS2010ImageLibrary).
После добавления графических файлов в проект они будут отображены в обозревателе решений (рис 4.14).
(рис 4.14) Включение в проект папки Images с файлами рисунковТеперь можно разработать XAML-описание панели инструментов для страницы PageEmployee.
Для каждой кнопки зададим свойство Name – имя объекта в программе и свойство ToolTip с текстом всплывающей подсказки при наведении указателя мыши на кнопку.
Свойство Margin определяет
<ToolBar Name="ToolBar1" Margin="3"> <Button Name="Undo" ToolTip="Отменить редактирование/создание" Margin="5,2,5,2"> <Image Source="Images/Undo.jpg" /> </Button> ... </ToolBar>
В дизайнере Visual Studio страница .
(рис 4.15) Страниц PageEmployee с панелью инструментов в дизайнереПосле запуска приложения и выборе кнопки панели инструментов .
Следующим шагом проектирования интерфейсных элементов для страницы PageEmployee является решение задачи формирования отображения данных по сотрудникам предприятия. Данная задача может быть решена различными способами: с помощью элементов контроля ListBox, ListView, TextBox, TextBlock, ComboBox, DataGrid и других.
(рис 4.16) Страница PageEmployee с панелью инструментовВ учебном примере будем использовать элемент контроля DataGrid для табличного отображения данных о сотрудниках. В качестве заголовка таблицы применим текстовый блок "Список сотрудников".
Класс DataGrid представляет элемент управления, отображающий данные в настраиваемой сетке строк и столбцов. По умолчанию DataGrid автоматически создает столбцы, на основе источника данных. При этом генерируются следующие типы столбцов:
Если разработчика не устраивает автоматическая генерация столбцов DataGrid можно её отключить. Для этого свойству AutoGenerateColumns необходимо присвоить значение false. Далее можно создать собственный набор столбцов ( Columns ), используя существующие типы столбцов или создать новый тип столбца с помощью шаблона DataGridTemplateColumn.
DataGrid поддерживает множество способов настройки отображения данных. В табл. 4.1 приведен список стандартных сценариев.
| Сценарий | Подход |
|---|---|
| Переменные цвета фона | Задайте для свойства AlternationIndex значение 2 или больше, а затем назначьте объект Brush свойствам RowBackground и AlternatingRowBackground. |
| Определение поведения при выборе ячейки и строки | Установите свойства SelectionMode и SelectionUnit. |
| Настройка внешнего вида заголовков, ячеек и строк | Примените новый Style к свойствам ColumnHeaderStyle, RowHeaderStyle, CellStyle или RowStyle. |
| Доступ к выбранным элементам | Проверьте свойство SelectedCells, чтобы получить выделенные ячейки, и свойство SelectedItems, чтобы получить выбранные строки. |
| Настройка взаимодействия с пользователем | Установите свойства CanUserAddRows, CanUserDeleteRows, CanUserReorderColumns, CanUserResizeColumns, CanUserResizeRows и CanUserSortColumns. |
| Отмена или изменение автоматически созданных столбцов | Обработать событие AutoGeneratingColumn. |
| Заморозка столбца | Задайте для свойства FrozenColumnCount значение 1 и переместите столбец в крайнюю левую позицию, задав для свойства DisplayIndex значение 0. |
| В качестве источника данных используются данные XML. | Привяжите ItemsSource в DataGrid к запросу XPath, представляющему коллекцию элементов. Создайте каждый столбец в DataGrid. Свяжите каждый столбец, указав XPath для привязки к запросу, который получает свойство из источника элемента. |
XAML-документ описания интерфейсных элементов страницы PageEmployee имеет следующий вид.
<TextBlock Margin="5" >Список сотрудников</TextBlock>
<DataGrid Name="DataGridEmployee" >
<DataGrid.Columns>
<DataGridTextColumn Header="Фамилия"/>
. . .
<DataGridComboBoxColumn Header="Должность" />
<DataGridTemplateColumn Header="Дата рождения" />
. . .
</DataGrid.Columns>
</DataGrid>
Для полей Фамилия, Имя, Отчество, Телефон и Электронная почта используется тип столбца DataGridTextColumn. Так как должность сотрудника задается в соответствии с данными из справочника базы данных, то есть предоставляется список, из которого можно произвести выбор, для данного столбца используется тип DataGridComboBoxColumn. Для столбца Дата рождения используется специфичный шаблон, то есть тип DataGridTemplateColumn, который будет описан позднее.
С учетом добавленных интерфейсных элементов страница .
(рис 4.17) Страница PageEmployee с элементом DataGrid в дизайнереПосле запуска приложения страница
(рис 4.18) Страница PageEmployee с элементом DataGridНа данном этапе проектирования приложения на странице PageEmployee размещены все необходимые элементы контроля.
Для реализации функциональности приложения в части обработки информации о сотрудниках предприятия необходимо для страницы PageEmployee установить механизм запуска задач ( Отменить, Создать, Редактировать, Сохранить, Найти и Удалить ) при выборе соответствующих пунктов меню и нажатии на кнопки панели инструментов. Технология WPF предлагает модель команд для выполнения такой привязки.
Модель команд обеспечивает
Классы, реализующие команды должны поддерживать интерфейс ICommand. В этом интерфейсе определены два метода Execute, CanExecute и событие CanExecuteChanged.
В WPF имеется библиотека базовых команд. Команды доступны через статические свойства следующих статических классов:
Для создания пользовательских команд целесообразно использовать классы RoutedCommand, который имеет
В разрабатываемом приложении для функций Отменить, Создать, Сохранить и Найти будем использовать команды и библиотеки WPF – статический класс ApplicationCommands, а для функций Редактировать и Удалить спроектируем пользовательские команды.
Для разработки пользовательских команд добавим в проект папку Commands и в ней создадим класс DataCommands.
public class DataCommands
{
public static RoutedCommand Delete { get; set;}
public static RoutedCommand Edit { get; set; }
static DataCommands()
{
InputGestureCollection inputs = new InputGestureCollection();
inputs.Add(new KeyGesture(Key.E, ModifierKeys.Control, "Ctrl+E"));
Edit = new RoutedCommand("Edit", typeof(DataCommands), inputs);
inputs = new InputGestureCollection();
inputs.Add(new KeyGesture(Key.D, ModifierKeys.Control, "Ctrl+D"));
Delete = new RoutedCommand("Delete", typeof(DataCommands), inputs);
}
}
В классе DataCommands объявлены два свойства Delete и Edit типа RoutedCommand. Класс RoutedCommand определяет команду, реализующую ICommand. В конструкторе данного класса определяется объект inputs типа InputGestureCollection. Класс InputGestureCollection представляет упорядоченную коллекцию объектов InputGesture, которые позволяют с помощью класса KeyGesture задать комбинацию клавиш для вызова команды.
Для использования страницей PageEmployee пользовательских команд в XAML-документе необходимо добавить пространство имен, где расположен класс DataCommands. Данному пространству имен присвоим ссылку command.
xmlns:command="clr-namespace:WpfApplProject.Commands"
Теперь для страницы PageEmployee сформируем коллекцию объектов CommandBinding, которая осуществляет привязку команд для данного элемента и объявляет связь между командой, ее событиями и обработчиками.
<Page.CommandBindings>
<CommandBinding Command="Undo"
Executed="UndoCommandBinding_Executed"
CanExecute="UndoCommandBinding_CanExecute" />
. . .
</Page.CommandBindings>
Для класса CommandBinding свойство Command определяет ссылку на соответствующую команду, а свойства Executed и CanExecute задают обработчики событий при выполнении команды.
На странице приложения используются следующие команды: Отменить, Создать, Редактировать, Поиск, Сохранить и Удалить. Команды могут быть доступны или недоступны пользователю при работе приложения. Это проверяет метод CanExecute при генерации события CanExecuteChanged, которое вызывается при изменении состояния команды. Доступность команд определяется состоянием, в котором находится приложение. В тоже время выполнение какой-либо команды переводит, как правило, приложение в какое-либо другое состояние. Для проектируемого приложения можно определить следующие состояния:
На рис 4.19 приведена диаграмма состояний приложения, на которой кружками обозначены состояния, а дуги соответствуют переходам при выполнении определенной команды.
(рис 4.19) Диаграмма состояний приложенияНа основе
| Состояние | Доступность команд | |||||
|---|---|---|---|---|---|---|
| Сохранить | Отменить | Создать | Поиск | Редактировать | Удалить | |
| 1 | false | false | true | true | true | true |
| 2 | false | false | true | true | true | true |
| 3 | true | true | false | false | false | false |
| 4 | true | true | false | false | false | false |
Из табл. 4.2 видно, что в приложении режим доступности команд в состояниях 1 и 2 противоположно режиму доступности команд в состояниях 3 и 4. Фактически для приложения имеются два режима (один объединяет состояния 1 и 2, а второй – состояния 3 и 4), управлять которыми можно с помощью
В код программы класса PageEmployee введем логическое поле isDirty для управления доступностью команд.
private bool isDirty = true;
В код класса добавим обработчики (реализация метода Executed ), определяющие бизнес-логику приложения. На данном этапе проектирования системы обработчики будут содержать только вывод сообщений о вызове команды и изменение поля isDirty. Код обработчика команды Удалить приведен ниже.
private void UndoCommandBinding_Executed(object sender,
ExecutedRoutedEventArgs e)
{
MessageBox.Show("Отмена");
isDirty = true;
}
В дальнейшем в обработчики добавим код для обеспечения требуемой функциональности.
В коде класса остается добавить обработчики (реализация метода CanExecute ), которые управляют доступностью команд. Так как при анализе табл. 4.2 было выявлено, что для приложения различимо только два состояния доступности команд, то и обработчиков тоже достаточно иметь в программе два.
private void EditCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = isDirty;
}
private void SaveCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = !isDirty;
}
Теперь необходимо модифицировать XAML-документ в части задания свойства Command при описании пунктов меню и панели инструментов для привязки команд.
При описании меню (Menu) XAML-документ модифицирован следующим образом.
<Menu>
<MenuItem Header="Действие" BorderThickness="3" >
<MenuItem Header="Отменить" Command="Undo"></MenuItem>
. . .
</Menu>
Соответствующие изменения XAML-документа необходимо провести и для панели инструментов ToolBar.
<ToolBar Name="ToolBar1" Margin="3">
<Button Name="Undo" Margin="5,2,5,2" Command="Undo"
ToolTip="Отменить редактирование/создание" >
<Image Source="Images/Undo.jpg">
</Image>
</Button>
...
</ToolBar>
При выполнении приложения различные состояния доступности пунктов меню приведены на рис 4.20 и рис 4.21.

(рис 4.21) Состояние доступности пунктов меню после загрузки приложения(рис 4.20) Состояние доступности пунктов меню после редактирования данныхПри выборе какого-либо пункта меню, например пункта Создать, система выдает сообщение (рис 4.22).
(рис 4.22) Выбор пункта меню СоздатьСледующим этапом разработки приложения является создание источника данных, который обеспечит взаимодействие приложения с базой данных.
Приложение WPF, пространство имен, атрибут, частичный класс, простое свойство, сложное свойство, фрейм, гиперссылка, меню, панель инструментов, команда, привязка команд.
MainWindow, xmlns, partial, InitializeComponent, NavigationWindow, Frame, FrameworkElement, Page,
В данной теме были рассмотрены вопросы разработки страничного WPF-приложения, организации перехода по страницам, создания системы меню, панели команд, табличного представления информации для просмотра и редактирования данных, системы универсальных команд многократного использования.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.