98515

Автоматизированное рабочее место библиотекаря

Курсовая

Информатика, кибернетика и программирование

Среда разработки Visual Studio Integrated Development Environment (IDE) - интегрированная среда разработки) включает набор инструментов и не зависит от используемых языков программирования, представленных в Visual Studio. Visual Studioможно использовать для создания кода и на различных языках программирования: управляемый C++ - Manadged C++, Visual Basic.NET, Java.NET, C#.

Русский

2015-11-04

8.47 MB

13 чел.

Предмет : "Средства визуального программирования приложений"

Программу необходимо написать в среде :  Microsoft Visual Studio 2008  на языке  С#

Тема курсовой:"Автоматизированное рабочее место библиотекаря"

 

Условия: Для книг, хранящихся в библиотеке,задаются

           -номер по порядку

           -автор книги (Ф.И.О.) ,

           -название книги,

           -год издания книги,

           -издательство книги,  

           -количество страниц в книге    

           -регистрационный номер книги,

           -номер стеложа где находится (лежит) книга

           (т.е.библиотекарь вручную должен всё это вписывать и оно должно сохраняться)

                 Потом необходимо вывести следующие варианты поиска книг :

      - вывести с соблюдением номера по порядку,весь список книг  в алфавитном порядке, с  

        инициалами авторов(Ф.И.О.) с названием книги,годом издательства,издательством,

        количеством страниц, регистрационным номером,и номером стеложа где находится книга

      - вывести с соблюдением номера по порядку, весь список книг  в алфавитном порядке, с  

        инициалами авторов(Ф.И.О.)  изданных после какого то заданного года и номером

        стеложа где находится книга

      - вывести  (найти) книгу  или книги(если  например их несколько томов ) с соблюдением  

        номера по порядку, после каких то заданных  инициалов или только одной фамилии,или

        полностью (Ф.И.О.) автора и номера стеложа где находятся  данные книги

        

        

По примеру ниже лабораторных работ необходимо написать курсовую работу тема и условия которой были изложены выше только в Microsoft Visual Studio 2008  на языке  С#.

  1.  Лабораторная работа: Создание главного окна приложения

в среде С#   

Содержание

  •  Основные сведения
  •  Обзор среды разработки C#
  •  Проектирование приложения
  •  Создание рабочей области проекта
  •  Класс System.Windows.Forms.Application
  •  Проектирование окна приложения
  •  Добавление нового кода в приложение
  •  Структура и синтаксис функции
  •  Задание на лабораторную работу

Цель работы: Изучить основные элементы среды разработки Visual Studio Integrated Development Environment ( IDE - интегрированная среда разработки) C# при создании на языке C# приложений с графически интерфейсом.

Основные сведения

Среда разработки Visual Studio Integrated Development Environment (IDE) - интегрированная среда разработки) включает набор инструментов и не зависит от используемых языков программирования, представленных в Visual StudioVisual Studioможно использовать для создания кода и на различных языках программирования: управляемый C++ - Manadged C++, Visual Basic.NET, Java.NET, C#.

В лабораторной работе проводится изучении среды разработки на языке программирования C# и следующих средств проектирования Windows - приложений:

основные окна среды разработки C#;

  •  построение базовой инфраструктуры с помощью Application Wizard (мастер создания приложений);
  •  использование дизайнера форм Dialog Painter (программа для рисования диалоговых окон) для оформления диалоговых окон;
  •  добавление новых функциональных возможностей в приложение с использованием вкладки Properties(свойства).

Обзор среды разработки C#

Для начала работы с Visual Studio.NET необходимо из главного меню выбрать пункт "Microsoft Visual Studio.NET" (VS). При этом на компьютере загрузится Developer Studio (визуальная среда разработки Microsoft Visual ) на экране компьютера будет выведено окно, изображенное на рисунке 1.1.

Проектирование приложения

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

  1.  Создать рабочую область, называемую также рабочей средой (проектирования), рабочим пространством и рабочей обстановкой нового проекта.
  2.  Для создания каркаса приложения можно использовать мастер создания приложений - Application Wizard.
  3.  Изменить внешний вид автоматически создаваемых мастером окон до желаемого вида.


Рис. 1.1.  Стартовое диалоговое окно IDE

  1.  Добавить код C#, который будет вызывать отображение приветствия.

Создание рабочей области проекта

В VS каждому разрабатываемому приложению нужна рабочая среда. Рабочая среда проекта состоит из папок, в которых хранятся файлы исходного кода, а также из папок, в которых хранятся различные конфигурационные файлы. Создание рабочей среды нового проекта производится следующим образом:

  1.  Щелкните на ссылке Project (Создать новый проект) метки Create на начальной странице (Start Page) VS.NET. При этом откроется окно создания нового проекта New Project (рисунок 1.2).


Рис. 1.2.  Мастер создания нового проекта (New Project Wizard)

  1.  В дереве, отображаемом в подокне Project Type (Типы проектов) выберите "Visual C# /Windows". В подокнеTemplates (Шаблоны) выберите Windows Application (Приложение Windows ).
  2.  В поле Name (Название проекта) наберите имя проекта - Project_К4И_01 (имя проекта присваивается в соответствии со следующим синтаксисом: Project_"номер группы"_"номер бригады в группе" ).
  3.  Щелкните на кнопке ОК. (Да). Мастер создания нового проекта создаст новый класс Form1, производный отSystem.Windows.Forms.Form с правильно настроенным методом Main( ). В свойствах проекта автоматически будут созданы ссылки на необходимые сборки библиотеки базовых классов. На экране появится графический шаблон среды разработки (рисунок 1.3).


Рис. 1.3.  Графический шаблон главного окна приложения

При помощи дизайнера графических форм можно добавлять в приложение любые элементы управления и он будет автоматически генерировать код для этих элементов (по умолчанию файл с главной формой приложения называется Form1.cs ).

Для просмотра кода сгенерированного приложения можно в окне Solution Explorer щелкнуть правой кнопкой мыши на файле Form1.cs и в контекстном меню выбрать View Code (рисунок 1.4).


Рис. 1.4.  Выбор режима View Code в контекстном меню

В результате будет выведен на экран следующий листинг кода приложения

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace Project_К4И_01

{

 public partial class Form1 : Form

 {

   public Form1()

  { InitializeComponent(); }

 }

}

Инициализация компонент реализуется кодом, который можно отобразить, в окне Solution Explorer щелкнуть на пункте Form.Designer.cs (рисунок 1.5).


Рис. 1.5.  Выбор режима Form.Designer.cs

namespace Project_К4И_01

{

 partial class Form1

 {

   private System.ComponentModel.IContainer components = null;

   protected override void Dispose(bool disposing)

   {

      if (disposing && (components != null))

      {

         components.Dispose();

      }

      base.Dispose(disposing);

   }

   #region Windows Form Designer generated code

   private void InitializeComponent()

   {

      this.components = new System.ComponentModel.Container();

      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

      this.Text = "Form1";

    }

    #endregion

 }

}

В определении класса Form1 используется ключевое слово partial, которое позволяет определять класс, структуру или интерфейс, распределенные по нескольким файлам. В Visual Studio 2005 классы Windows -форм формируются в двух файлах: Form1.cs и Form1.Designer.cs. В файле Form1.Designer.cs присутствует код, сгенерированный дизайнером Windows -формы, а файле Form1.cs - присутствует код инициализации класса и пользовательские члены класса (поля, свойства, методы, события, делегаты)

Код приложения (Program.cs) имеет следующий вид:

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace Project_К4И_01

{

 static class Program

  {

    [STAThread]

    static void Main()

   {

    Application.EnableVisualStyles();

    Application.SetCompatibleTextRenderingDefault(false);

    Application.Run(new Form1());

   }

  }

}

Метод Main является точкой входа для приложения и вызывает Application.Run, который создает класс Form1.

Класс System.Windows.Forms.Application

Класс Application можно рассматривать как "класс низшего уровня", позволяющий нам управлять поведением приложения Windows Forms. Кроме того, этот класс определяет набор событий уровня всего приложения, например закрытие приложения или простой центрального процессора.

Наиболее важные методы этого класса (все они являются статическими) перечислены в таблице 1.1.

Таблица 1.1. Наиболее важные методы типа Application

Метод класса

Назначение Application

AddMessageFilter( )

Эти методы позволяют приложению перехватывать сообщения RemoveMessageFilter( ) и выполнять с этими сообщениями необходимые предварительные действия. Для того чтобы добавить фильтр сообщений, необходимо указать класс, реализующий интерфейсIMessageFilter

DoEvents( )

Обеспечивает способность приложения обрабатывать сообщения из очереди сообщений во время выполнения какой-либо длительной операции. Можно сказать, что DoEvents() - это "быстрый и грязный" заменитель нормальной многопоточности

Exit( )

Завершает работу приложения

ExitThred( )

Прекращает обработку сообщений для текущего потока и закрывает все окна, владельцем которых является этот поток

OLERequired( )

Инициализирует библиотеки OLE. Можете считать этот метод эквивалентом .NET для вызываемого вручную метода Olelnitialize( )

Run( )

Запускает стандартный цикл работы с сообщениями для текущего потока

Класс Application определяет множество статических свойств (таблице 1.2), большинство из которых доступны только для чтения.

Таблица 1.2. Наиболее важные свойства типа Application

Свойство

Назначение

CommonAppDataRegistry

Возвращает параметр системного реестра, который хранит общую для всех пользователей информацию о приложении

CompanyName

Возвращает имя компании

CurrentCulture

Позволяет задать или получить информацию о естественном языке, для работы с которым предназначен текущий поток

CurrentlnputLanguage

Позволяет задать или получить информацию о естественном языке для ввода информации, получаемой текущим потоком

ProductName

Для получения имени программного продукта, которое ассоциировано с данным приложением

ProductVersion

Позволяет получить номер версии программного продукта

StartupPath

Позволяет определить имя выполняемого файла для работающего приложения и путь к нему в операционной системе

Многие из этих свойств предназначены для получения общей информации о приложении, такой как название компании, номер версии и т.п.

Таким образом, при помощи многих свойств (например, CompanyName или ProductName ) можно очень просто получить метаданные уровня сборки. В сборке можно использовать любое количество встроенных и пользовательских атрибутов. В результате можно получить значение атрибута [assembly:AssemblyCompany(" ")] при помощи свойства Application.CompanyName без необходимости прибегать к использованию типов, определенных в пространстве имен System.Reflection.

Проектирование окна приложения

Для разметки окон приложения в соответствии с требованиями пользователя необходимо изменить свойства класса Forms1. Это можно сделать с помощью дизайнера окон ( Form Designer ), путем изменения свойств в окне Свойства ( Properties ) или в коде программы.

Размеры окна можно изменить непосредственно в Form Designer с помощью мыши захватывая и, растягивая/сжимая границы окна.

Для изменения других свойств окна необходимо окно свойств Properties.

На вкладке Properties измените значение в поле Text (Заголовок) наПроект К4И. При этом на форме изменится заголовок окна (рисунок 1.6).


увеличить изображение
Рис. 1.6.  Изменение значения в поле Text на вкладке Properties

Откомпилируйте приложение, выбрав из главного меню команду Build Project_К4И_01 (рисунок 1.7)


Рис. 1.7.  Выбор из главного меню команды Build

В строке состояний должно появиться сообщение:

Build succeeded

Для запуска приложения выберите из главного меню команду Debug/Start (F5). Приложение запустится в отладочном режиме и на экране появится разработанное окно (рисунок 1.8.).


Рис. 1.8.  Окно приложения Project_К4И_01

Для закрытия окна щелкните мышью на кнопке

Добавление нового кода в приложение

Добавим в главную форму элемент контроля - кнопку. Для этого откроем вкладку ToolBox (рисунок 1.9) и сначала щелкнем мышью на элементе Button вкладки, а затем щелкнем мышью на форме.


Рис. 1.9.  Вкладка ToolBox

В результате получим форму с кнопкой (рисунок 1.10).


Рис. 1.10.  Форма с установленной кнопкой

Установите кнопку в требуемое место на форме с помощью мыши.

Для задания текста на кнопке выделите ее на форме и откройте вкладку Свойства и измените свойство Text на "Приветствие". В результате название кнопки изменится (рисунок 1.11).


Рис. 1.11.  Форма с измененным свойством Text кнопки

Для связывания функций кнопки с диалоговым окном необходимо создать обработчик события на нажатие кнопки. Для этого сделайте двойной щелчок на кнопке. В результате в коде приложения сформируется шаблон функции обработчика события Click для кнопки.

private void button1_Click(object sender, EventArgs e)

       {

       }

В полученный шаблон добавим функцию вывода диалогового окна с сообщением.

private void button1_Click(object sender, EventArgs e)

  {

   // Сообщение

   MessageBox.Show("Поздравляю с первым проектом на C#");

   }

После компиляции и запуска приложения получим следующее окно приложения (рисунок 1.12), а при нажатии кнопки будет выведено сообщение (рисунок 1.13).


Рис. 1.12.  Результат выполнения приложения


Рис. 1.13.  Вывод сообщения

Структура и синтаксис функции

Рассмотрим код листинга функции:

private void button1_Click(object sender, EventArgs e)

  {

  // Сообщение

  MessageBox.Show("Поздравляю с первым проектом на C#");

  }

Первая строка является частью оболочки функции, сгенерированной Developer Studio на языке C#.

Первое слово в строке, private определяет видимость функции как внутреннюю, т.е. видимую только для членов класса Form1. Второе слово void, определяет тип данных возвращаемого значения (результата). Ключевое слово void, - перед именем функции, или в качестве аргумента функции (в скобках в конце строки), означает отсутствие соответствующего элемента. Третье слово в строке, button1_Click, обозначает имя функции. За именем функции следует список передаваемых ей аргументов, заключенный в круглые скобки. Круглые скобки нужно использовать всегда, даже когда у функции нет параметров.

Правило 1. В C# при вызове функции за ее именем должны стоять круглые скобки, даже если данной функции не передается ни один параметр.

В следующей строке листинга открывающая фигурная скобка ( { ) отмечает начало тела функции. В конце тела функции ставится закрывающая фигурная скобка ( } ).

Правило 2. Тело функции всегда заключается в фигурные скобки {}.

Следующая строка начинается с двух косых черт, или слешей ( // ). Все, что следует до конца строки после двух идущих подряд косых черт (без пробелов, табуляций и т.п. между ними) рассматривается компилятором как комментарий и игнорируется. Исключением являются строки, в которых косая черта является частью текстовой, или литерной строки (строки букв). Это один из способов комментирования кода. Второй способ чаще используется при добавлении в код нескольких строк комментариев. В этом случае начало комментария обозначается идущими подряд косой чертой и звездочкой ( /* ), а конец комментария завершается таким же набором символов, но переставленных в обратном порядке ( */ ).

Последняя строка в добавленном нами коде (в тексте это две строки):

MessageBox.Show("Поздравляю с первым проектом на C#");

Во-первых, C# чувствителен к регистру. В именах функций и переменных заглавные (прописные) буквы должны использоваться точно так же, как в их объявлениях. Это означает, что компилятор распознает следующие имена функций как имена трех различных функций:

MessageBox.Show   messageBox.Show    messagebox.Show

Правило 3. Язык C# чувствителен к регистру. При вводе программ, написанных на языке C#, учитывайте регистр. В частности, все идентификаторы вводите с учетом регистра.

За именем функции следуют аргументы функции, заключенные в круглые скобки, а после скобок стоит точка с запятой. Аргументы разделяются запятыми.

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать Windows форму.
  3.  На Windows форме создать кнопку "Приветствие".
  4.  Протестировать работу приложения
  5.  Добавить в форму две кнопки (1 и 2), для которых задать различные цвета (свойство BackColor ).
  6.  Написать для кнопок 1 и 2 обработчики, которые изменяют цвета кнопок: при неоднократном нажатии любой кнопки цвета кнопок меняются ( цвет кнопки 1 меняется на цвет кнопки 2 и наоборот).
  7.  Добавьте кнопку "Выход". Закрытие приложения обеспечивает метод Exit( ) класса Application.
  8.  Протестировать работу приложения.

2. Лабораторная работа: Создание главного меню приложения

Содержание

  •  Указания по использованию .NET
  •  Создание меню
  •  Задание на лабораторную работу

Цель работы: Изучить основные способы разработки главного меню приложении. Получить практические навыки в создании главного меню приложения.

Указания по использованию .NET

В любом языке программирования существуют традиционные стили программирования. Эти стили являются не частью самого языка, а соглашениями, скажем, по именованию переменных или использованию определенных классов, методов или функций. Если большинство разработчиков будут следовать одинаковым соглашениям, то им будет проще понять код друг друга, что, в свою очередь, облегчает поддержку программы. Так, общим соглашением в Visual Basic 6 было то, что строковые переменные должны иметь имена, начинающиеся с s или str, например String sResult или String strMessage. Однако соглашения зависят от языка и среды разработки. Программисты на C++ для платформы Windows традиционно используют префикс psz или lpsz для обозначения строк: char *pszResult; char *lpszMessage;. Но на Unix-машинах такие префиксы не применяются: char *Result; char *Message;.

В соответствии с соглашениями в С# имена переменных не должны иметь префиксов: string Result; string Message;.

Соглашение, согласно которому имена переменных содержат префикс, указывающий тип данных, известно как "венгерский" стиль именования объектов. При чтении такого кода разработчики могут сразу же сказать по имени переменной, какой тип данных она представляет.

В то время как для многих языков соглашения по именованию вырабатывались одновременно с развитием языка, для С# и платформы .NET Microsoft написала подробные рекомендации по использованию, которые приведены в документации MSDN для .NET/C#. Следовательно, с самого начала программы .NET будут иметь более высокий уровень совместимости по части понимания кода другими разработчиками. Эти рекомендации были разработаны с учетом опыта, полученного на протяжении более двадцати лет объектно-ориентированного программирования, и в результате являются тщательно продуманными и хорошо восприняты сообществом разработчиков.

Однако необходимо отметить, что рекомендации не то же самое, что спецификации языка. Рекомендаций следует придерживаться по мере возможности. Если имеется веская причина для их несоблюдения, это не будет проблемой. Отклонение от рекомендаций должно быть вызвано реальными причинами, а не простым нежеланием.

Одним из важных моментов является выбор имен для элементов программы: переменных, методов, классов, перечислений и пространств имен.

Очевидно, что названия обязаны отражать назначение элемента и не должны конфликтовать с другими именами.

Общая философия платформы .NET состоит в том, что имя переменной должно отражать назначение экземпляра переменной, а не тип данных.

Например, Height - хорошее название, a IntegerValue - нет. Однако этот принцип является труднодостижимым идеалом. В частности, при работе с элементами управления в большинстве случаев вам будет удобнее использовать имена переменных, подобные ConfirmationDialog и ChooseEmployeeListBox.

Конкретные рекомендации по именованию включают в себя следующие разделы.

Практически во всех случаях для имен следует использовать стиль Pascal, при котором первая буква каждого слова в названии является прописной

Например: EmployeeSalary, ConfirmationDialog, PlainTextEncoding.

Соединение слов с помощью знака подчеркивания не приветствуется, поэтому не придумывайте такие имена, как employee_salary. В других языках часто используют все прописные буквы в названиях констант. Это не рекомендуется в С#, поскольку такие имена трудно читать, лучше применять паскалевский стиль:

const int MaximumLength;

Еще одна рекомендуемая схема - именование в стиле camel. Именование camel аналогично паскалевскому стилю, за исключением того, что первая буква первого слова не является прописной: employeeSalary, confirmationDialog, plainTextEncoding.

Существуют две ситуации, в которых лучше применять такое именование. Имена всех параметров, передаваемых в методы, должны записываться в стиле camel:

public void RecordSale (string salesmanName,int guanuity);

Также можно использовать camel -соглашение для того, чтобы отличить два элемента, которые в противном случае имели бы одинаковые имена. Наиболее общий случай, когда свойство является оболочкой для поля.

private string employeeName;

public string EmployeeName

{ get

    { return employeeName; }

}

Приведенный код является совершенно корректным с точки зрения рекомендаций. Отметим, однако, что в этом случае следует применять соглашение camel для закрытых членов и соглашение Pascal для открытых или защищенных членов, чтобы другие классы, использующие ваш код, видели только имена в стиле Pascal (за исключением имен параметров).

В большинстве случаев следует применять соглашения Pascal. Тем не менее, соглашение camel рекомендуется для закрытых переменных, которые не видны вне класса, где две переменные имеют одинаковое назначение. Например, если есть public свойство, которое инкапсулирует private поле с тем же именем, то можно использовать соглашение camel для поля и соглашение Pascal для свойства, как в приведенном выше примереEmployeeName.

Также необходимо обращать внимание на чувствительность к регистру. С# чувствителен к регистру, поэтому синтаксически в С# допустимо, чтобы имена различались только регистром. Однако нужно помнить, что ваши сборки могут быть вызваны из приложений VB.NET, a VB.NET не является чувствительным к регистру. Поэтому использовать имена, отличающиеся только регистром, можно лишь в том случае, если они никогда не будут видны вне сборки. В противном случае код, написанный в VB.NET, не сможет корректно использовать вашу сборку.

Необходимо по возможности делать так, чтобы стиль всех имен совпадал. Например, если один из методов в классе называется ShowConfirmationDialog, то другому методу не следует давать имя ShowDialogWarning илиWarningDialogShow. Он должен называться ShowWarningDialog.

Имена пространств имен следует выбирать особенно тщательно для того, чтобы избежать использования такого же имени, которое применяется где-то еще. Необходимо помнить, что .NET различает имена объектов в разделяемых сборках только по именам пространств имен. Если использовать для двух пакетов программного обеспечения одно и то же имя пространства имен и установить оба пакета на один компьютер, возникнут проблемы. Рекомендуется создавать пространство имен верхнего уровня с именем вашей компании, а затем вкладывать пространства имен, постепенно сужая их названия до технологии, группы или отдела, где вы работаете, или до названия пакета, для которого предназначены ваши классы. Microsoft рекомендует имена пространств имен, которые начинаются с <НазваниеКомпании>.<НазваниеТехнологии>, например,

WeaponsOfDestructionCorp.RayGunControllers

или

WeaponsOfDestructionCorp.Viruses.

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

Создание меню

В пространстве имен System.Windows.Forms предусмотрено большое количество типов для организации ниспадающих главных меню (расположенных в верхней части формы) и контекстных меню, открывающихся по щелчку правой кнопки мыши.

Элемент управления ToolStrip представляет собой контейнер, используемый для создания структур меню, панелей инструментов и строк состояний.

Элемент управления MenuStrip - это контейнер для структур меню в приложении. Этот элемент управлении наследуется от ToolStrip. Система меню строится добавлением объектов ToolStripMenu к menuStrip.

Класс ToolStripMenuItem служит для построения структур меню. Каждый объект ToolStripMenuItemпредставляет отдельный пункт в системе меню.

Начнем с создания стандартного ниспадающего меню, которое позволит пользователю выйти из приложения, выбрав пункт Объект > Выход. Для этого необходимо перетащить элемент управления MenuStrip (рисунок 2.1) на форму в конструкторе.


Рис. 2.1.  Элемент управления MenuStrip

Элемент управления MenuStrip позволит вводить текст меню непосредственно в элементы меню. То, что должно получиться, представлено на рисунке 2.2.


Рис. 2.2.  Простое меню на форме

При помощи графических средств можно настроить свойства любого элемента меню. Для пункта меню "Объект"зададим свойство Name равным objektToolStripMenuItem, для пункта меню "Выход" ) -exitToolStripMenuItem, а для пункта меню "Справка" - HelpToolStripMenuItem.

При двойном щелчке на пункте меню "Выход" (объект exitToolStripMenuItem ) Visual Studio автоматически сгенерирует оболочку для обработчика события Click и перейдет в окно кода, в котором нам будет предложено создать логику метода (в нашем случае exitToolStripMenuItem_Click ):

private void exitToolStripMenuItem_Click(object sender, EventArgs e)

  {

// Здесь мы определяем реакцию на выбор пользователем

// пункта меню

    }

На вкладке Свойства (Properties) при выводе окна событий, нажать кнопкусобытию Click будет соответствовать метод menuItemExit_Click (рисунок 2.3).


Рис. 2.3.  Событие Click и обработчик события exitToolStripMenuItem_Click

Для корректного завершения приложения написать код для обработчика exitToolStripMenuItem_Click. Это можно сделать с помощью метода Exit класса Application:

private void exitToolStripMenuItem_Click(object sender, EventArgs e)

 {

   Application.Exit();

 }

Для тестирования созданного меню создадим обработчик для пункта меню "Объект", который будет сообщать, что выбран именно этот пункт меню.

private void objektToolStripMenuItem_Click(object sender, EventArgs e)

 {

   MessageBox.Show("Пункт меню Объект");

 }

При создании меню графическими средствами Visual Studio автоматически внесет необходимые изменения в служебный метод InitializeComponent и добавит переменные-члены, представляющие созданные элементы меню.

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать главное меню, включающее следующие пункты: "Объект", "Справочник", "Справка".
  3.  Для пункта "Объект" создать следующие подпункты: "Сотрудник", "Клиент", "Договор", "Поручение", "Сделка", "Выход".
  4.  Для пункта "Справочник" создать следующие подпункты: "Должность", "Страна", "Регион", "Город", "ИМНС".
  5.  Для пункта "Справка" создать подпункт - "О программе"
  6.  Протестировать работу приложения.

3. Лабораторная работа: Создание многооконного приложения

Содержание

  •  Создание дочерней формы
  •  Создание меню в дочерней форме
  •  Создание обработчиков для меню дочерней формы
  •  Задание на лабораторную работу

Цель работы: Изучить основные способы разработки многооконных приложений. Получить практические навыки в создании многооконных приложений.

Создание дочерней формы

Основа Интерфейса ( MDI ) приложения - MDI родительская форма. Это - форма, которая содержит MDI дочерние окна. Дочерние окна являются "подокнами", с которыми пользователь взаимодействует вMDI приложении. Создание MDI родительской формы описано в лабораторной работе 2.

Для определения главного окна ( Form1 ), как родительской формы в окне Свойств, установите IsMDIContainerсвойство - true. Это определяет форму как MDI контейнер для дочерних форм. Для того чтобы родительское окно занимало весь экран необходимо свойству WindowsState установить значение Maximized.

Создайте еще одно окно, которое будет дочерним ( FormEmployee ). Для этого выберите пункт меню Project/Add Windows Form.

Это окно должно вызываться из пункта главного меню "Сотрудник". Вставьте код, подобный следующему, чтобы создать новую MDI дочернюю форму, когда пользователь щелкает на пункте меню, например "Сотрудник" - имя объекта - employeeToolStripMenuItem (В примере ниже, указатель события обращается к событию Click дляemployeeToolStripMenuItem_Click ).

private void menuItemEmploye_Click(object sender,

System.EventArgs e)

{ // Создать объект FEmployee класса FormEmployee

FormEmployee FEmployee = new FormEmployee();

 // Установить родительское окно для дочернего

FEmployee.MdiParent = this;

// Вывести на экран дочерее окно

FEmployee.Show();

}

Данный обработчик приведет к выводу на экран дочернего окна.

Создание меню в дочерней форме

Добавьте в (Свойствах в графе Name) дочернее окно пункт меню "Действие" ( actionToolStripMenuItem ) с подпунктами "Отменить" (undoToolStripMenuItem ), "Создать" ( createToolStripMenuItem ), "Редактировать" ( editToolStripMenuItem ), "Сохранить" ( saveToolStripMenuItem ) и "Удалить" ( removeToolStripMenuItem ). Перед пунктом удалить вставьте разделитель ( Separator - name = toolStripSeparator1 ).

Добавьте в дочернее окно еще один пункт меню "Отчет" ( reportToolStripMenuItem ) c подпунктами "По сотруднику" ( reportToolStripMenuItem1 ), "По всем сотрудникам" ( reportToolStripMenuItem2 ). Дочернее окно будет иметь вид, представленный на рисунке 3.1


Рис. 3.1.  Дочернее окно с меню

В главном меню родительской формы ( Form1 ) имеются пункты "Объект", "Справочник" и "Справка". В дочерней форме ( FormEmployee ) сформированы пункты меню "Действие" и "Отчет". При загрузке дочерней формы меню родительской и дочерних форм должны были объединены и составлять следующую последовательность: "Объект", "Действие", "Отчет", "Справочник" и "Справка". Объединение пунктов меню производится с помощью задания значений свойств MergeAction и MergeIndex для объектов ToolStripMenuItem.

Проверьте, чтобы в меню главного окна(материнская форма) для объекта objectToolStripMenuItem свойство MergeAction было установлено Append, а MergeIndex было равно 0, а для объектов dictionaryToolStripMenuItem иhelpToolStripMenuItem - соответственно 1 и 2. С учетом этого, в окне "Сотрудник" для объектовactionToolStripMenuItem (Действие) и "Отчет" ( reportToolStripMenuItem ) свойству MergeAction необходимо задать значение Insert, а свойству MergeIndex задаем порядковый номер который определяет позицию данного пункта меню обновленном главном меню, т.е. 1 (после объекта objectToolStripMenuItem ).

После компиляции программы, запуска ее на выполнение и вызова пункта меню "Сотрудник" экран должен иметь вид, представленный на рисунке 3.2.


Рис. 3.2.  Дочернее окно с подключенным меню

Создание обработчиков для меню дочерней формы

Созданные пункты меню для дочернего окна должны инициировать выполнение соответствующих функций (Отменить, Создать, Редактировать, Сохранить и Удалить) приложения в отношении объектов конкретного дочернего окна. Для дочернего окна "Данные по сотруднику" эти функции должны выполнять соответственно отмену редактирования данных по сотруднику (функция "Отменить"), создавать новые данные по сотруднику (функция "Создать"), редактировать данные по сотруднику (функция "Редактировать"), сохранять созданные вновь или отредактированные функция по сотруднику (функция "Сохранить") и удалять данные по сотруднику (функция "Удалить").

Описанную функциональность целесообразно реализовать в программе в виде методов класса созданного FormEmployee. В приложении необходимо создать следующие методы:

  •  Undo - отменить;
  •  New - создать;
  •  Edit - редактировать;
  •  Save - сохранить;
  •  Remove - удалить.

На начальных этапах проектирования, как правило, неясна реализация каждого метода, поэтому целесообразно их выполнять в виде методов-заглушек, которые только сообщают пользователю о своем вызове, а в дальнейшем необходимо написать реальный код.

Для создания метода Undo в коде файла FormEmployee.cs добавьте следующий метод:

private void Undo( )

{  MessageBox.Show("метод Undo"); }

Далее создаем обработчик события вызова пункта меню "Отменить". Для этого в дизайнере формы классаFormEmployee делаем двойной щелчок на пункте меню "Отменить". Инструментальная среда VS сгенерирует следующий код:

private void undoToolStripMenuItem_Click(object sender, EventArgs e)

  {  

  }

В код обработчика undoToolStripMenuItem_Click добавим вызов метода Undo:

private void undoToolStripMenuItem_Click(object sender, EventArgs e)

 {  

    Undo();

 }

Откомпилируем приложение и протестируем вызов метода Undo. В результате выбора пункта меню "Отменить" должно быть выведено диалоговое окно с сообщением, приведенным на рисунке 3.3.


Рис. 3.3.  Дочернее окно с подключенным меню

Аналогичным образом создайте методы-заглушки для функций "Создать", "Редактировать", "Сохранить" и "Удалить".

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать дочернее окно.
  3.  В дочернее окно добавить пункты меню.
  4.  Написать обработчик для вызова из главного меню дочернего окна.
  5.  Создать коды методов-заглушек для функций приложения.
  6.  Создать обработчики для вызова пунктов меню.
  7.  Протестировать работу приложения.

4. Лабораторная работа: Создание пользовательских диалоговых окон

Содержание

  •  Основные сведения
  •  Задание на лабораторную работу

Цель работы: Изучить основные способы построения диалоговых окон, их параметры и получить практические навыки в разработке

Основные сведения

Диалоговое окно - это форма, обладающая некоторыми специальными характеристиками. Первая отличительная черта большинства диалоговых окон - то, что их размер изменять нельзя. Кроме того, в диалоговых окнах обычно не используются элементы управления, помещаемые в верхнюю часть обычных форм: ControlBoxMinimizeBox и MaximizeBox. Для пользователя диалоговое окно в противоположность обычному является практически неизменяемым.

Диалоговые окна бывают модальные и немодальные. Если приложение открывает модальное окно, то работа приложения блокируется до тех пор, пока не будет закрыто модальное окно. Немодальные окна могут работать одновременно с породившим их главным окном приложения. Такие окна часто используются для "плавающих" инструментальных панелей, настройки различных параметров приложения, причем отсутствие модальности позволяет использовать в приложении измененные параметры, не закрывая окна настройки этих параметров.

Простейшее модальное диалоговое окно можно создать на базе класса MessageBox, входящего в библиотеку Microsoft .NET Framework. В лабораторной работе 3 иллюстрировалось применение простейшего модального диалогового окна для вывода сообщения об активизации метода Undo. Для отображения диалогового окна использовался метод Show, передав ему через параметр текст сообщения "метод Undo". Прототип использованного методаShow следующий:

public static DialogResult Show(string message);

Когда пользователь щелкает кнопку ОК, метод Show возвращает значение, равное DialogResult.OK

Существует множество перегруженных вариантов метода MessageBox.Show, позволяющих задать необходимый внешний вид диалоговой панели, а также количество и тип расположенных на ней кнопок.

Прототип наиболее общего варианта метода MessageBox.Show, позволяющий реализовать практически все возможности диалогового окна MessageBox, приведен ниже

public static DialogResult Show

{

string message, //  текст сообщения

string caption, //  заголовок окна

MessageBoxButtons btns, // кнопки,  расположенные в окне

MessageBoxIcon icon, //  значок, расположенный в окне

MessageBoxDefaultButton  defButton, // кнопка по умолчанию

MessageBoxOptions  opt // дополнительные параметры

};

Параметр caption позволяет задать текст заголовка диалогового окна MessageBox. С помощью параметра btns можно указать, какие кнопки необходимо расположить в окне диалогового окна. Этот параметр задается константами из перечисления MessageBoxButtons (таблица 4.1)

Таблица 4.1. Перечисление MessageBoxButtons

Константа

Кнопки, отображаемые в окне MessageBox

ОК

OK

OKCancel

OK, Cancel

YesNo

Yes, No

YesNoCancel

Yes, No, Cancel

RetryCancel

Retry, Cancel

AbortRetryIgnore

Abort, Retry, Ignore

Параметр icon метода MessageBox.Show позволяет выбрать один из нескольких значков для расположения в левой части диалогового окна. Он задается в виде константы перечисления MessageBoxIcon (таблица 4.2).

Таблица 4.2. Перечисление MessageBoxIcon

Константа

Значок

Asterisk, Information

Error, Stop

Exclamation, Warning

Question

None

Значок не отображается

Параметр defButton метода MessageBox.Show предназначен для выбора кнопки, которая получит фокус сразу после отображения диалогового окна. Этот параметр должен иметь одно из значений перечисления MessageBoxDefaultButton (таблица 4.3).

Таблица 4.3. Перечисление MessageBoxDefaultButton

Константа

Номер кнопки, получающей фокус ввода по умолчанию

Button l

1

Button 2

2

Button 3

3

Если в диалоговом окне отображаются кнопки YesNo и Cancel, то они будут пронумерованы последовательно: кнопка Yesполучит номер 1 (константа Button1 ), кнопка No - номер 2 (константа Button2 ), а кнопка Cancel - номер 3 (константаButton3 ).

Параметр opt метода MessageBox.Show позволяет задать дополнительные параметры. Эти параметры должны иметь значения из перечисления MessageBoxOptions (таблица 4.4).

Таблица 4.4. Перечисление MessageBoxOptions

Константа

Описание

DefaultDesktopOnly

Окно с сообщением отображается только на рабочем столе, выбранном по умолчанию

RightAlign

Текст сообщения выравнивается по правому краю диалогового окна

RtlReading

Текст отображается справа налево

ServiceNotification

Окно отображается на активном рабочем столе, даже если к системе не подключился ни один пользователь. Данный параметр предназначен для приложений, работающих как сервисы ОС Microsoft Windows

Если в окне диалогового окна MessageBox имеется несколько кнопок, то для того, что бы определить, какую кнопку щелкнул пользователь, программа должна проанализировать значение, возвращенное методом MessageBox.Show.

Метод MessageBox.Show может вернуть одно из нескольких значений перечисления DialogResult (таблица 4.5).

Таблица 4.5. Перечисление DialoqResult

Константа

Кнопка, при щелчке которой возвращается эта константа

Abort

Abort

Cancel

Cancel

Ignore

Ignore

No

No

None

Модальное диалоговое окно продолжает работать

OK

OK

Retry

Retry

Yes

Yes

Изменим метод Remove, добавив в него предупреждение перед удалением данных по сотруднику. Текст кода метода Removeдолжен иметь следующий вид:

private void Remove()

{

   DialogResult result = MessageBox.Show(" Удалить данные  \n по сотруднику? ",

     "Предупреждение", MessageBoxButtons.YesNo, MessageBoxIcon.Warning,

       MessageBoxDefaultButton.Button2);

   switch (result)

   {

       case DialogResult.Yes:

           {

//выполнить действия по удалению данных по сотруднику

               MessageBox.Show("Удаление данных");

               break;

           }

       case DialogResult.No:

           {

//отмена удаления данных по сотруднику   

               MessageBox.Show("Отмена удаления данных");

               break;

           }

   }

В результате исполнения кода приложения и выбора пункта меню "Удалить" будет выводиться предупреждение, приведенное на рисунке 4.1 .


Рис. 4.1.  Модальное диалоговое окно предупреждения

Диалоговое окно можно создать не только на основе класса MessageBox, но и с использованием Windows - формы.

Создадим новую форму FormAbout для вывода справочной информации о разрабатываемом приложении, которое должно иметь вид представленный на рисунке 4.2 .


Рис. 4.2.  Общий вид Windows - формы FormAbout

Для этого добавим в проект новый компонент (рисунок 4.3), выбрав из списка AboutBox (рис. 4.4).


Рис. 4.3.  Выбор режима добавления нового компонента в проект

Рис. 4.4.  Добавление нового компонента в проект

Для класса AboutBox можно задать логотип и дополнительную информацию. По умолчанию данный класс берет дополнительную информацию из метаданных сборки. Проверьте это.

Мы введем собственную информацию. Для этого изменим фрагмент кода конструктора класса AboutBox1 следующим образом.

public AboutBox1()

{

 InitializeComponent();

 this.Text = String.Format("О программе {0}", AssemblyTitle);

 this.labelProductName.Text = AssemblyProduct;

 this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);

 this.labelCopyright.Text = "@БГУ, 2012";

 this.labelCompanyName.Text = "Данилова Г.В.";

 this.textBoxDescription.Text = "Дисциплина Средства визуального программирования приложений.";

}

Для открытия пользовательского модального диалогового окна используется метод ShowDialog. В лабораторной работе диалоговое окно должно открываться при щелчке пользователем на пункте в меню "Справка/О программе". Код для открытия диалогового окна может выглядеть следующим образом:

// Открываем модальное диалоговое окно

private void aboutToolStripMenuItem_Click(object sender, EventArgs e)

{

   AboutBox1 aboutBox = new AboutBox1();

   aboutBox.ShowDialog(this);

}

Модальность формы определяет именно метод ShowDialog: при использовании кода ход выполнения программы будет приостановлен вплоть до того момента, пока метод ShowDialog не вернет соответствующее значение. Для пользователя это значит, что ему придется закрыть диалоговое окно, прежде чем он сможет выполнить какие-либо операции на главной форме.

После компиляции и загрузки приложения, вызвав пункт меню "Справка/О программе" на дисплеи будет выведено диалоговое окно, приведенное на рисунке 4.5.

Рис. 4.5.  Вызов модального окна

При нажатии на кнопку ОК диалоговое окно будет автоматически закрыто и в ходе дальнейшего выполнения программы можно выяснить значение свойства DialogResult.

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать модальное диалоговое окно с помощью класса MessageBox.
  3.  Создать пользовательское модальное диалоговое окно для пункта меню "О программе".
  4.  Написать обработчики для вызова модальных окон.
  5.  Протестировать работу приложения.

5. Лабораторная работа: Создание панели инструментов и контекстного меню

Содержание

  •  Разработка панели инструментов
  •  Контекстное меню
  •  Задание на лабораторную работу

Цель работы: Изучить основные способы построения панели инструментов и контекстного меню, их параметры и получить практические навыки в разработке.

В приложении для повышения качества интерфейса пользователя целесообразно предусматривать различные способы активизации функций системы. При выполнении лабораторной работы 3 для приложения было создано меню, которое позволяет активизировать функции "Отменить", "Создать", "Редактировать", "Сохранить" и "Удалить". Данные функции могут быть активизированы с помощью кнопок панели инструментов и контекстного меню.

Разработка панели инструментов

Элемент управления ToolStrip используется непосредственно для построения панелей инструментов. Данный элемент использует набор элементов управления, происходящих от класса ToolStripItem.

В Visual Studio.NET предусмотрены средства, которые позволяют добавить панель инструментов при помощи графических средств. Для этого необходимо открыть панель Toolbox и добавьте элемент управленияToolStrip (рисунок 5.1) на разрабатываемую форму FormEmployee.

Рис. 5.1.  Окно свойств панели инструментов

В выпадающем меню элемента управления ToolStrip на форме FormEmployee необходимо выбрать элемент управления button - кнопка (рисунок 5.2). При этом в панели инструментов добавится кнопка.


Рис. 5.2.  Окно свойств панели инструментов

Добавьте на панель инструментов кнопки с именами toolStripButtonUndo, toolStripButtonNew, toolStripButtonEdit, toolStripButtonSave, toolStripButtonRemove. В результате должна быть сформирована панель инструментов с кнопками (рисунок 5.3).


Рис. 5.3.  Форма FormEmployee с панелью инструментов

Для кнопок панели инструментов сформируем графическое представление. Это можно сделать путем задания свойства Image соответствующей кнопке (рисунок 5.4).

При открытии коллекции свойства Image соответствующей кнопки, нажатии кнопкиоткрывается окно мастера выбора графического ресурса (рисунок 5.5).

Рис. 5.4.  Свойство Image для кнопки панели инструментов

Рис. 5.5.  Добавление изображения в ImageList

С помощью кнопки Import в локальный ресурс добавляют ссылки на необходимые графические файлы, для формирования изображения кнопок. Результаты формирования графического представления кнопок панель инструментов приведены на рисунке 5.6. Графические файлы расположены в папке Visual Studio 2005\VS2005ImageLibrary\bitmaps\commands\16color (для лабораторной работы графические файлы можно найти в папке Лабораторные работы).

Рис. 5.6.  Форма с панелью инструментов

Каждая кнопка панели инструментов, которая является объектом класса toolStripButton, может содержать текст, или изображение, или и то и другое.

Созданная панель инструментов содержит пять кнопок. По функциональности каждой из этих кнопок будут соответствовать пункты меню "Отменить", "Создать", "Редактировать", "Сохранить" и "Удалить".

Для удобства пользователя целесообразно снабдить кнопки панели инструментов всплывающими подсказками при фокусировке курсора на данной кнопке. Это можно сделать, если свойству ToolTipText классаtoolStripButton задать значение текстовой строки с содержанием подсказки. На рисунке 5.7 для кнопки "Отменить" ( toolStripButtonUndo ) строка подсказки ToolTipText соответствует строке "Отменить".


Рис. 5.7.  Формирование подсказки для кнопки

На рисунке 5.8 показан вывод подсказки при фокусировке курсора на кнопкепанели инструментов.


Рис. 5.8.  Вывод подсказки для кнопки

Для распознавания реакции приложения при нажатии кнопок панели инструментов необходимо создать обработчик события для кнопок. При двойном нажатии на кнопку панели инструментов генерируется обработчик, в который нужно добавить вызов метода Undo. В этом случае обработчик нажатия кнопки панели инструментов будет иметь следующий вид:

private void toolStripButtonUndo_Click(object sender, EventArgs e)

{

   Undo();

}

Контекстное меню

Класс ContextMenuStrip применяется для показа контекстного меню, или меню, отображаемого по нажатию правой кнопки мыши. Для создания объекта класса ContextMenuStrip необходимо открыть панель Toolbox и добавить элемент управления contextMenuStrip на форму FormEmployee (рисунок 5.9).

Рис. 5.9.  Формирование на форме контекстного меню

В результате получаем форму FormEmployee с контекстным меню (рисунок 5.10)


Рис. 5.10.  Форма с контекстным меню

Формирование пунктов контекстного меню производится аналогично формированию пунктов главного меню (смотри лабораторную работу 2). Сформированное контекстное меню приведено на рисунке 5.11.


Рис. 5.11.  Вид контекстного меню

После формирования пунктов контекстного меню необходимо его подключить к форме FormEmployee. Для этого на вкладке Свойства ( Properties ) формы FormEmployee строке, соответствующей свойству ContextMenuStripнужно установить значение созданного объекта contextMenuStrip1 (рис. 5.12)


Рис. 5.12.  Подключение контекстного меню к форме

После компиляции проекта и запуска приложения на выполнение можно проверить режим активизации контекстного меню. Для этого необходимо выбрать из главного меню пункт "Сотрудник" и на появившейся форме в любом месте щелкнуть правой кнопкой мыши. Результат всплытия на форме контекстного меню показан на рисунке 5.13.


Рис. 5.13.  Активизация контекстного меню

Привязка пунктов контекстного меню к конкретным функциям осуществляется путем создания кода обработчика событий для каждого пункта меню. Для формирования обработчика необходимо перейти в окно дизайнера формы FormEmployee, выделить на форме класс ContextMenuStrip и сделать двойной щелчок на соответствующем пункте меню, например "Отменить". В сгенерированном обработчике необходимо добавить вызов метода, для функции "Отменить" - метод Undo( ). Листинг обработчика метода приведен ниже.

private void undo1ToolStripMenuItem_Click(object sender, EventArgs e)

{

   Undo();

}

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать панель инструментов.
  3.  Создать контекстное меню.
  4.  Написать обработчики для панели инструментов и контекстного меню.
  5.  Протестировать работу приложения

6. Лабораторная работа: Создание строки состояния

Содержание

  •  Создание строки состояния
  •  Задание на лабораторную работу

Цель работы: Изучить основные способы построения строки состояния и получить практические навыки в разработке

Создание строки состояния

На многих формах в реальных приложениях имеется элемент интерфейса, называемый строкой состояния ( StatusStrip ). Обычно в строке состояния выводится некоторая текстовая или графическая информация, относящаяся к работе приложения. Строка состояния может быть разделена на несколько "панелей" ( panel ) - отдельных частей окна. В каждой из этих панелей информация выводится отдельно.

Создадим строку состояния, в которой будут выводиться текстовые сообщения, относящиеся к пунктам меню.

В окне Toolbox выделим пункт StatusStrip и перетащим его на форму (рисунок 6.1).


Рис. 6.1.  Добавляем на форму строку состояния

Объекту класса StatusStrip присвоим имя statusStripEmployee. Откроем выпадающий список объекта классаstatusBarEmployee и выберем объект StatusLable (рисунок 6.2). Присвоим ему имяtoolStripStatusLabelEmployee.


Рис. 6.2.  Добавляем метку в строку состояния

При компиляции, запуске приложения и выборе пункта меню "Сотрудник" экранная форма будет иметь вид, представленный на рисунке 6.3.


Рис. 6.3.  Окно приложения со строкой состояния

Для управления текстом строки состояния необходимо разработать обработчик события для соответствующих объектов.

Для формы FormEmployee в строке состояний необходимо вывести информацию при наведении курсора мыши на пунктах меню "Действие". Первоначально в дизайнере формы необходимо выделить пункт меню "Действие", перейти на вкладку Properties и открыть окно событий, нажав кнопкуНа данной вкладке необходимо выделить событие MouseEnter и в поле ввода сделать двойной щелчок. (рисунок 6.4).


Рис. 6.4.  Окно событий

Система сгенерирует код обработчика, приведенного ниже.

private void actionToolStripMenuItem_MouseEnter(object sender, EventArgs e)

{   }

Добавим в обработчик следующий код:

private void actionToolStripMenuItem_MouseEnter(object sender, EventArgs e)

{

  toolStripStatusLabelEmployee.Text =

       "Выбор действий по сотрудникам";

}

Если откомпилировать программу, запустить её, выбрать пункт меню "Сотрудник" и навести указатель мыши на пункт "Действие", то сгенерируется событие "MouseEnter" и в строке состояния выведется текстовое сообщение "Выбор действий по сотрудникам" (рисунок 6.5).


Рис. 6.5.  Вывод сообщения в строке состояния

Если теперь переместить указатель мыши с пункта меню "Действие", то текст в строке состояния не изменится. Такой режим работы программы является неправильным, так как если указатель мыши перемещается с пункта меню "Действие", то строка состояния должна становиться пустой. Для обеспечения правильной работы программы воспользуемся ещё одним событием "MouseLeave", которое генерируется, когда мышь перемещается (покидает) с пункта меню "Действие". Обработчик данного события имеет следующий вид:

private void actionToolStripMenuItem_MouseLeave(object sender, EventArgs e)

{

   toolStripStatusLabelEmployee.Text = "";

}

Вышеприведенные обработчики будут вызываться только тогда, когда пользователь наведет указатель мыши на пункт меню "Действие". Для того чтобы обработчики реагировали на все строки пунктов главного меню"Действие" и "Отчет" формы FormEmployee необходимо сформировать соответствующие события MouseEnter иMouseLeave для всех подпунктов меню и создать для них обработчики.

Результаты компиляции и выполнения приложения приведены на рисунке 6.6.


Рис. 6.6.  Экранная форма со строкой состояния

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Создать строку состояний для главной и дочерней форм.
  3.  Написать обработчики для формирования строки состояний, отображающих информацию о пунктах меню.
  4.  Протестировать работу приложения.

7. Лабораторная работа: Создание элементов управления

Содержание

  •  Общие сведения
    •  Элемент управления TextBox
    •  Класс Button
    •  Флажки
    •  Переключатели и группирующие рамки
    •  Элемент управления CheckedListBox
    •  Комбинированные списки
    •  Порядок перехода по Tab
    •  Элемент управления MonthCalendar
    •  Элемент управления Panel
    •  Всплывающие подсказки (ToolTips)
  •  Проектирование элементов управления формы FormEmployee
  •  Задание на лабораторную работу
  •  Цель работы: Изучить основные элементы управленияWindows -форм, их свойства и методы, а также получить практические навыки в разработке Windows -форм с элементами контроля
  •  Общие сведения
  •  Классы, представляющие графические элементы управления, находятся в пространстве именSystem.Windows.Forms. С их помощью обеспечивается реакция на действия пользователя в приложенииWindows Forms.  Классы элементов управления связаны между собой достаточно сложными отношениями наследования. Общая схема таких отношений представлена на рисунке 7.1.
  •  Класс Control, как общий предок, обеспечивает все производные классы общим набором важнейших возможностей. В числе этих возможностей можно перечислить события мыши и клавиатуры, физические размеры и местонахождение элемента управления (свойства Height, Width, Left, Right, Location ), установку цвета фона и цвета переднего плана, выбор шрифта и т.п.
  •  При создании приложения можно добавить элементы управления на форму при помощи графических средствVisual Studio. Обычно достаточно выбрать нужный элемент управления в окне ToolBox и поместить его на форме.Visual Studio автоматически сгенерирует нужный код для формы. После этого можно изменить название элемента управления на более содержательное (например, вместо button1, предлагаемого по умолчанию, - buttonPrimer) Visual Studio позволяет не только размещать на форме элементы управления, но и настраивать их свойства. Для этого достаточно щелкнуть на элементе управления правой кнопкой мыши и в контекстном меню выбратьProperties (Свойства).


Рис. 7.1.  Иерархия элементов управления Windows Forms

Все изменения, которые необходимо произвести в открывшемся окне (рисунок 7.2), будут добавлены в код метода InitializeComponents().


Рис. 7.2.  Настройка элементов управления средствами Visual Studio

То же самое окно позволяет настроить не только свойства данного элемента управления, но и обработку событий этого элемента. Перейти в список событий можно при помощи кнопкив закладке Properties(рисунок 7.3). Можно выбрать в списке нужное событие и рядом с ним сделать двойной щелчок или ввести имя метода или выбрать метод из списка.


Рис. 7.3.  Настройка обработчиков событий

После задания имени метода или двойного щелчка Visual Studio сгенерирует заготовку для обработчика события.

Рассмотрим основные элементы управления Windows -форм.

Элемент управления TextBox

Элемент управления TextBox (текстовое окно) предназначен для хранения текста (одной или нескольких строк). При желании текст в TextBox может быть настроен как "только для чтения", а в правой и нижней части можно поместить полосы прокрутки.

Класс TextBox происходит непосредственно от класса TextBoxBase, обеспечивает общими возможностями какTextBox, так и RichTextBox. Свойства, определенные в TextBoxBase, представлены в таблице 7.1.

Таблица 7.1. Свойства TextBoxBase

Свойство

Назначение

AcceptsTab

Определяет, что будет производиться при нажатии на клавишу Tab: вставка символа табуляции в само поле или переход к другому элементу управления

AutoSize

Определяет, будет ли элемент управления автоматически изменять размер при изменении шрифта на нем

BackColor, ForeColor

Позволяют получить или установить значение цвета фона и переднего плана

HideSelection

Позволяет получить или установить значение, определяющее, будет ли текст в TextBoxоставаться выделенным после того, как этот элемент управления будет выведен из фокуса

MaxLength

Определяет максимальное количество символов, которое можно будет ввести в TextBox

Modified

Позволяет получить или установить значение, определяющее, был ли текст в TextBoxизменен пользователем

Multiline

Указывает, может ли TextBox содержать несколько строк текста

Readonly

Помечает TextBox как "только для чтения"

SelectedText, SelectionLength

Содержат выделенный текст (или определенное количество символов) в TextBox

SelectionStart

Позволяет получить начало выделенного текста в TextBox

Wordwrap

Определяет, будет ли текст в TextBox автоматически переноситься на новую строку при достижении предельной длины строки

  •  В TextBoxBase также определено множество методов: для работы с буфером обмена ( Cut, Copy и Paste ), отменой ввода ( Undo ) и прочими возможностями редактирования ( Clear, AppendText и т. п.).
  •  Из всех событий, определенных в TextBoxBase, наибольший интерес представляет событие TextChange. Это событие происходит при изменении текста в объекте класса, производном от TextBoxBase. Например, его можно использовать для проверки допустимости вводимых пользователем символов (например, предположим, что пользователь должен вводить в поле только цифры или, наоборот, только буквы).
  •  Свойства, унаследованные от Control и от TextBoxBase, определяют большую часть возможностей TextBox. Свойств, определенных непосредственно в классе TextBox, не так уж и много. Они представлены в таблице 7.2.

Таблица 7.2. Свойства, определенные в классе TextBox

Свойство

Назначение

AcceptsReturn

Позволяет определить, что происходит, когда пользователь при вводе текста нажал на Enter. Варианта два: либо в TextBox начинается новая строка текста, либо активизируется кнопка по умолчанию на форме

CharacterCasing

Позволяет получить или установить значение, определяющее, будет ли изменяться регистр вводимых пользователем символов

PasswordChar

Позволяет выбрать символ, используемый для отображения вводимых пользователем данных (в поле для ввода пароля)

ScrollBars

Позволяет получить или установить значение, определяющее, будут ли в TextBox с несколькими строками присутствовать полосы прокрутки

TextAlign

Позволяет определить выравнивание текста в TextBox (используются значения из перечисления HorizontalAlignment )

  •  Значения перечисления HorizontalAlignment представлены в таблице 7.3.

Таблица 7.3. Значения перечисления HorizontalAlignment

Значение

Описание

Center

Выравнивание по центру

Left

Выравнивание по левому краю

Right

Выравнивание по правому краю

  •  Класс Button
  •  Кнопка ( button ) - это самый простой из всех элементов управления и при этом наиболее часто используемый. Можно сказать, что кнопка - это возможность принять ввод (щелчок кнопкой мыши или набор на клавиатуре) наиболее простым способом. Непосредственный предок класса System.Windows.FormButton в иерархии классов.NET - это класс ButtonBase, обеспечивающий общие возможности для целой группы производных от него элементов управления (таких как Button, CheckBox и RadioButton ). Некоторые свойства ButtonBaseпредставлены в таблице 7.4.

Таблица 7.4. Свойства ButtonBase

Свойство

Назначение

FlatStyle

Позволяет настроить "рельефность" кнопки. Используются значения из перечисления FlatStyle

Image

Позволяет задать изображение, которое будет выводиться на кнопке (при этом можно указать точное местонахождение изображения). Фоновый рисунок лучше настраивать при помощи свойства BackgroundImage, определенного в базовом классе Control

ImageAlign

Позволяет определить выравнивание изображения, размещенного на кнопке. Используются значения из перечисления ContentAlignment

Imagelndex, ImageList

Эти свойства используются для работы с набором изображений (объектом ImageList ), выводимых на кнопке

IsDefault

Определяет, будет ли эта кнопка являться кнопкой по умолчанию (то есть срабатывать при нажатии на Enter )

TextAlign

Позволяет получить или установить выравнивание текста на кнопке. Также используются значения из перечисления ContentAlignment

  •  Сам класс Button не определяет каких-либо дополнительных возможностей помимо унаследованных отButtonBase, за единственным, но существенным исключением свойства DialogResult. Это свойство позволяет возвращать значение при закрытии диалогового окна, например, при нажатии кнопок ОК или Cancel (Отменить).
  •  В подавляющем большинстве случаев выравнивание текста, размещенного на кнопке, производится по центру, так что текст будет размещен строго посередине кнопки. Однако если нам по каким-то причинам необходимо использовать другой стиль выравнивания, в нашем распоряжении - свойство TextAlign, определенное в классеButtonBase. Для TextAlign используются значения из перечисления ContentAlignment (таблица 7.5). Значения из того же перечисления используются и для определения положения изображения на кнопке.

Таблица 7.5. Значения перечисления ContentAlignment

Значение

Описание (выравнивание)

BottomCenter

По нижнему краю кнопки, относительно боковых краев - посередине

BottomLeft

Но нижнему краю кнопки, слева

BottomRight

По нижнему краю кнопки, справа

MiddleCenter

По центру кнопки

MiddleLeft

Относительно верхнего и нижнего краев - по центру, относительно боковых краев - слева

MiddleRight

Относительно верхнего и нижнего краев - по центру, относительно боковых краев - справа

TopCenter

По верхнему краю кнопки, относительно боковых краев - посередине

TopLeft

По верхнему краю кнопки, слева

TopRight

По верхнему краю кнопки, справа

  •  Флажки
  •  Для флажка (тип CheckBox ) предусмотрено три возможных состояния. Как и тип Button, CheckBox наследует большую часть своих возможностей от базовых классов Control и ButtonBase. Однако в этом классе существуют и свои собственные члены, обеспечивающие дополнительные уникальные возможности. Наиболее важные свойства CheckBox представлены в таблице 7.6.

Таблица 7.6. Свойства класса CheckBox

Свойство

Назначение

Appearance

Настраивает вид флажка. Для этого свойства используются значения из перечисления Appearance

AutoCheck

Позволяет получить или установить значение, определяющее, будут ли значения Checked и CheckState, а также внешний вид флажка автоматически изменяться при щелчке на нем

CheckAlign

Позволяет установить горизонтальное и вертикальное выравнивание собственно флажка (квадратика) в элементе управления CheckBox. Используются значения из перечисленияContentAlignment

Checked

Возвращает значение типа bool, представляющее текущее состояние флажка (выбран или не выбран) Если для свойства ThreeState установлено значение true, то свойство Checked будет возвращать true как для явно выбранного флажка, так и для того флажка, для которого установлено значение "не определено" ( indeterminate )

CheckState

Позволяет получить или установить значение флажка (установлен - не установлен - не определено), используя не true и false, как в Checked, а три значения из перечисленияCheckState. Обычно используется, если свойство ThreeState для флажка имеет значение true (то есть он допускает три значения).

ThreeState

Определяет, будут ли для флажка использоваться три значения (из перечисления CheckState ) или только два

  •  Возможные состояния флажка ( Indeterminate можно использовать только тогда, когда для свойстваThreeState установлено значение true ) представлены в таблице 7.7.

Таблица 7.7. Значения перечисления CheckState

Значение

Описание

Checked

Флажок установлен

Indeterminate

Значение не определено (обычно флажок выглядит как "серый", затененный)

Unchecked

Флажок снят

  •  Состояние "значение не определено" ( indeterminate ) может быть установлено, например, для верхнего элемента иерархии, в которой для одной части подчиненных элементов флажок установлен, а для другой - снят.

Переключатели и группирующие рамки

Тип RadioButton (переключатель) можно воспринимать, как несколько видоизмененный флажок при этом сходство между этими типами подчеркивается почти полным совпадением наборов членов. Между типами RadioButton и CheckBox существуют лишь два важных различия: в RadioButton предусмотрено событие CheckedChanged (возникающее при изменении значения Checked ), а кроме того, RadioButton не поддерживает свойство ThreeState и не может принимать состояниеIndeterminate (не определено).

Переключатели всегда используются в группах, которые рассматриваются как некое единое целое. Внутри группы переключателей одновременно может быть выбран только один переключатель. Для группировки переключателей в группы используется тип GroupBox.

И флажок ( CheckBox ), и переключатель ( RadioButton ) поддерживают свойство Checked, при помощи которого очень удобно получать информацию о состоянии соответственно флажка и переключателя. Однако если есть необходимость задействовать дополнительное третье состояние флажка (не определено - Indeterminate ), то придется вместоChecked использовать свойство CheckState и значения из одноименного перечисления CheckState.

Элемент управления CheckedListBox

Типы Button, CheckBox и RadioButton являются производными от ButtonBase, и их можно определить как некие разновидности кнопок. К членам семейства списков относятся CheckedListBox (список с флажками), ListBox(список) и ComboBox (комбинированный список).

Элемент управления CheckedListBox (список с флажками) позволяет помещать обычные флажки внутри поля с полосами прокрутки.

Кроме того, в элементе управления CheckedListBox предусмотрена возможность использования нескольких столбцов. Для этого достаточно установить значение true для свойства MultiColumn.

CheckedListBox наследует большинство своих возможностей от типа ListBox. To же самое справедливо и в отношении класса ComboBox. Наиболее важные свойства System.Windows.Forms.ListBox представлены в таблице 7.8.

Таблица 7.8. Свойства класса ListBox

Свойство

Назначение

ScrollAlwaysVisible

Определяет, будет ли полоса прокрутки выводиться всегда

Selectedlndex

Индекс выделенного в настоящий момент элемента в списке (если такой имеется). Если ни один элемент не выделен, то возвращается значение -1

SelectedIndices

Набор индексов выделенных в настоящий момент элементов в списке. Если не выделен ни один элемент, то возвращается пустой набор

SelectedItem

Значение выделенного в настоящий момент элемента. Если ни один из элементов не выделен, то возвращается null

SelectedItems

Возвращает коллекцию значений выделенных элементов (для списков, в которых допускается выбор нескольких значений)

SelectionMode

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

Sorted

Определяет, будут ли элементы в списке упорядочены (по алфавиту) или нет

TopIndex

Возвращает индекс первого видимого элемента в списке

Помимо свойств в классе ListBox определены также многочисленные методы. Подавляющее большинство этих методов дублирует возможности, предоставляемые в наше распоряжение свойствами, поэтому мы их рассматривать не будем.

Комбинированные списки

Как и списки (объекты ListBox ), комбинированные списки (объекты ComboBox ) позволяют пользователю производить выбор из списка заранее определенных элементов. Однако у комбинированных списков есть одно существенное отличие от обычных: пользователь может не только выбрать готовое значение из списка, но и ввести свое собственное. Класс ComboBox наследует большинство своих возможностей от класса ListBox(который, в свою очередь, является производным от Control ), однако в нем предусмотрены и собственные важные свойства, представленные в таблице 7.9.

Таблица 7.9. Свойства ComboBox

Свойство

Назначение

DroppedDown

"Раскрывающийся вниз": определяет, будет ли список ниспадающим

MaxDropDownltems

Определяет максимальное количество элементов, которое будет показано в нижней части ниспадающего списка. Допустимые значения - от 1 до 100

MaxLength

Определяет максимальную длину текста, который пользователь может ввести в ComboBox

Selectedlndex

Определяет индекс выделенного элемента ComboBox. Если ни один элемент не выделен, возвращается значение -1

Selectedltem

Возвращает ссылку на объект выделенного элемента ComboBox

SelectedText

Возвращает выделенный текст в поле редактирования ComboBox

SelectionLength

Определяет длину (в символах) выделенного текста в поле редактирования ComboBox

Style

Позволяет получить или установить стиль ComboBox. Для этого свойства используются значения из перечисления ComboBoxStyle

Text

Позволяет получить доступ к тексту в поле редактирования. При работе с ComboBox это унаследованное свойство используется чаще всех остальных

Стиль для ComboBox можно настроить при помощи свойства Style, для которого используются значения из перечисления ComboBoxStyle (таблица 7.10).

Таблица 7.10. Значения перечисления ComboBoxStyle

Значение

Описание

DropDown

Пользователь может вводить значения в поле редактирования. Для отображения списка пользователь должен нажать на кнопку со стрелкой, направленной вниз ( Arrow Button )

DropDownList

Пользователь не может вводить значения в поле редактирования. Для отображения списка пользователь должен нажать на кнопку со стрелкой, направленной вниз ( Arrow Button )

Simple

Пользователь может вводить значения в поле редактирования. Список значений виден всегда

Порядок перехода по Tab

Если на форме размещено несколько элементов управления, то пользователи обычно ожидают, что между ними можно будет перемещаться с помощью клавиши Tab. Часто бывает необходимо после размещения элементов управления настроить порядок перехода между ними. Для этого используются два свойства (унаследованные от базового класса Control и поэтому общие для всех элементов управления): TabStop и Tablndex. Для свойстваTabStop используются только два значения: true и false. Если для TabStop установлено значение true, то к этому элементу управления можно будет добраться с помощью клавиши Tab. Если же установлено значениеfalse, то участвовать в переходах по Tab этот элемент управления не будет. Если элемент управления TabStopимеет значение true, то очередность перехода можно настроить с помощью свойства Tablndex:

В Visual Studio.NET предусмотрено средство, при помощи которого можно быстро настроить порядок перехода для элементов управления на форме. Это средство называется Tab Order Wizard и оно доступно из меню View (View > Tab Order). Чтобы изменить значения TabIndex для каждого элемента управления, достаточно просто щелкать мышью на элементах управления в выбранном нами порядке перехода. Для элементов управления, помещенных в группирующую рамку, Tab Order Wizard создает отдельную последовательность перехода.

Элемент управления MonthCalendar

В пространстве имен System.Windows.Forms предусмотрен элемент управления, при помощи которого пользователь может выбрать дату или диапазон дат, используя дружественный и удобный интерфейс. Это элемент управления MonthCalendar.

Наиболее важные свойства MonthCalendar представлены в табл. 7.11.

Таблица 7.11. Свойства MonthCalendar

Свойство

Назначение

BoldedDates

Массив объектов DateTime, выделенных подсветкой

CalendarDimensions

Определяет количество выводимых строк и столбцов

FirstDayOfWeek

Определяет, с какого дня будет начинаться неделя в MonthCalendar

MaxDate

Самая поздняя дата, которую разрешается выбрать пользователю (по умолчанию ограничений нет)

MaxSelectionCount

Максимальное количество дат, которое одновременно может выбрать пользователь

MinDate

Самая ранняя дата, которую разрешается выбрать пользователю (по умолчанию ограничений нет)

MonthlyBoldedDates

Массив выделенных подсветкой объектов DateTime для месяца

SelectionRange

Диапазон выделенных объектов

SelectionEnd

Самая поздняя дата в диапазоне выделенных объектов

SelectionStart

Самая ранняя дата в диапазоне выделенных объектов

ShowToday

Определяет, будет ли MonthCalendar выводить информацию о текущей дате

ShowTodayCircle

Определяет, будет ли MonthCalendar выводить информацию о текущей дате в нижней части и выделять ее в календаре обводкой

ShowWeekNumbers

Определяет, будет ли MonthCalendar отображать номера недель справа от каждой строки

TodayDate

Дата, которая будет считаться MonthCalendar сегодняшней. По умолчанию TodayDate - это системная дата на момент создания объекта MonthCalendar

TodayDateSet

Определяет, можно ли пользователю по своему усмотрению выбирать сегодняшнюю дату. Если для этого свойства установлено значение true, пользователь может выбрать в качестве сегодняшней ( TodayDate ) любое число

По умолчанию всегда выделяется (и подсветкой, и обводкой) текущая дата. Пользователь может выбрать другую дату - в этом и есть смысл графического интерфейса MonthCalendar.

Можно получить дату, выбранную пользователем в MonthCalendar, при помощи свойства SelectionStart. Это свойство возвращает ссылку на объект DateTime, которая хранится в специальной переменной ( d ) При помощи набора свойств типа DateTime можно извлечь всю необходимую информацию в нужном нам формате.

При помощи свойств Month, Day и Year можно извлечь из объектов DateTime нужную информацию и сформировали текстовые строки. Это вполне допустимый подход. Дело в том, что дату в необходимом текстовом формате проще получить из DateTime при помощи специальных "форматирующих" свойств самих объектовDateTime. Набор таких свойств (и некоторые методы) представлен в таблице 7.12.

Таблица 7.12. Члены класса DateTime

Член

Назначение

Date

Позволяет получить информацию о дате (дата всегда отсчитывается от полуночи)

Day, Month, Year

Позволяют получить соответственно день, месяц и число из текущего объекта DateTime

DayOfWeek

Возвращает день недели для объекта DateTime

DayOfYear

Возвращает номер дня в году для объекта DateTime

Hour, Minute, Second, Millisecond

Возвращают информацию о часе, минутах, секундах и миллисекундах для объекта DateTime

MaxValue, MinValue

Возвращают минимальное и максимальное значения для DateTime

Now, Today

Эти два статических свойства типа DateTime позволяют получить информацию о текущей дате и времени ( Now ) или только о текущей дате ( Today )

Ticks

Позволяет получить счетчик "тиков" (с интервалом в 100 наносекунд) для объекта DateTime

ToLongDateString( ), ToLongTimeString( ), ToShortDateString( ), ToShortTimeString( )

Преобразуют текущее значение объекта DateTime в разные виды текстового представления

При помощи вышеперечисленных членов можно значительно упростить вывод текстовой информации о дате.

Элемент управления Panel

Назначение элемента управления Panel (панель) - с его помощью можно объединить прочие элементы управления на форме. Panel происходит от базового класса ScrollableControl и поддерживает полосы прокрутки.

Элементы управления Panel обычно используются для экономии пространства на форме. Например, если элементы управления, которые планируем разместить на форме, на ней не умещаются, то можно поместить их внутрь Panel и установить для свойства AutoScrol1 объекта Panel значение true. В результате пользователь получит возможность доступа к "не вмещающимся" элементам управления с помощью полос прокрутки.

Всплывающие подсказки (ToolTips)

Большинство приложений с современным пользовательским интерфейсом поддерживают всплывающие подсказки. В приложениях .NET эта возможность реализуется при помощи типа System.Windows.Forms.ToolTip.ToolTip (всплывающие подсказки) - это небольшие окна с текстом, появляющиеся при наведении указателя мыши на элемент управления на форме. Наиболее важные члены класса ToolTip представлены в таблице 7.13.

Таблица 7.13. Члены класса ToolTip

Член

Назначение

Active

Определяет, будет ли всплывающая подсказка активной. Возможность отключить всплывающие подсказки может быть полезной, например, если в приложении предусмотрено два варианта интерфейса: для обычных и для опытных пользователей

AutomaticDelay

Позволяет получить или установить время задержки (в миллисекундах) при появлении подсказки

AutoPopDelay

Время (в миллисекундах), в течение которого подсказка остается видимой, если указатель мыши неподвижен и находится в области, занимаемой соответствующим элементом управления. По умолчанию это значение равно 10 значениям AutomaticDelay

GetTooltip( )

Возвращает текст подсказки

InitialDelay

Время (в миллисекундах), в течение которого указатель должен оставаться неподвижным в соответствующей области для появления подсказки. Значение по умолчанию равно значению AutomaticDelay

ReshowDelay

Время (в миллисекундах), в течение которого появится другая подсказка при перемещении указателя мыши от одного элемента управления к другому. По умолчанию это значение равно 1/5 от значения AutomaicDelay

SetToolTip( )

Ассоциирует подсказку с элементом управления

Для того чтобы настроить использование всплывающих подсказок для элементов управления можно сделать это с помощью графических средств Visual Studio.

Первое, что необходимо сделать - добавить на форму объект ToolTip, выбрав его в ТооlBох. Затем можно указать текст всплывающей подсказки для любого элемента управления на форме (в том числе и для самой формы) из окна свойств данного элемента.

Проектирование элементов управления формы FormEmployee

Для разработки проекта приложения форма FormEmployee должна содержать элементы управления, в соответствии с видом, приведенном на рисунке 7.4 .


Рис. 7.4.  Вид экранной формы FormEmployee

На данной форме необходимо сформировать элементы управления, приведенные в таблице 7.14.

Таблица 7.14. Элементы управления формы FormEmployee

Элемент контроля

Имя

Свойство Text/Items

Назначение

SplitContainer

splitContainerEmployee

Две панели с разделителем

Label

labelListEmployee

Список сотрудников

Надпись

listBox

listBoxEmployee

Список сотрудников

Label

labelSurname

Фамилия

Надпись

Label

labelName

Имя

Надпись

Label

labelPatronymic

Отчество

Надпись

Label

labelJobRole

Должность

Надпись

Label

labelStatus

Статус

Надпись

Label

labelAccess

Уровень доступа

Надпись

label

labelNetName

Сетевое имя

Надпись

textBox

textBoxNetName

Сетевое имя

textBox

textBoxSurname

Фамилия

textBox

textBoxName

Имя

textBox

textBoxPatronymic

Отчество

comboBox

comboBoxJobRole

Должность

comboBox

comboBoxStatus

Активен, выходной, в отпуске, болеет, не работает, помечен как удаленный

Статус

comboBox

comboBoxAccess

Оператор, старший оператор, начальник смены, администратор, аналитик

Уровень доступа

menuItem

menuItemAction

Действие

Пункт меню "Редактировать"

menuItem

menuItemUndo

Отменить

Подпункт меню "Отменить"

menuItem

menuItemNew

Создать

Подпункт меню "Новый"

menuItem

menuItemEdit

Изменить

Подпункт меню "Изменить"

menuItem

menuItemSave

Сохранить

Подпункт меню "Сохранить"

menuItem

menuItem

Удалить

Подпункт меню "Удалить"

menuItem

menuItemReport

Отчет

Пункт меню "Отчет"

menuItem

menuItemReport1

По сотруднику

Подпункт меню "Отчет по сотруднику"

menuItem

menuItemReport2

По всем сотрудникам

Подпункт меню "Отчет по всем сотрудникам"

Вначале создайте на форме элемент SplitContainer (рисунок 7.5). На панели 1 создайте элементы управленияlabelListEmployee и listBoxEmployee (рисунок 7.6), а остальные элементы управления, приведенные в таблице 7.14, - на панели 2 (рисунок 7.4).

После создания на форме FormEmployee элементов управления в соответствии с таблицей 7.14 необходимо настроить порядок перехода между ними при нажатии клавиши Tab.


Рис. 7.5.  Создание панелей на форме FormEmployee



Рис. 7.6.  Формирование элементов управления на панели 1 формы FormEmployee

Для этого необходимо задать последовательные номера свойству TabIndex элементов управления (в разрабатываемой форме это необходимо сделать для элементов управления TextBox и ComboBox ) из окнаProperties (рисунок 7.7) или вызвать мастер Tab Order Wizard из меню View/Tab Order (рисунок 7.8). Задание последовательности значений свойству TabIndex производится щелчком мыши на элементах управления в заданной последовательности.


Рис. 7.7.  Задание свойства TabIndex для элемента контроля



Рис. 7.8.  Настройка перехода по элементам управления

Результат настройки порядка перехода между элементами управления при нажатии клавиши Tab приведен на рисунке 7.9.

Для работы с формой необходимо создать методы, которые разрешают только просматривать форму (режим просмотра) и редактировать форму (режим редактирования).


Рис. 7.9.  Результат работы мастера Tab Order Wizard

Создадим метод для задания режима просмотра формы DisplayReadOnly. Метод DisplayReadOnly должен быть общедоступным, ничего не должен возвращать и не иметь параметров. Для задания режима просмотра (только для чтения) объекту класса TextBox необходимо свойству ReadOnly присвоить значение true, а для объекта класса comboBox - свойству Enabled значение false. Код метода DisplayReadOnly представлен далее:

public void DisplayReadOnly()

{

   this.textBoxSurname.ReadOnly = true;

   this.textBoxName.ReadOnly = true;

   this.textBoxPatronymic.ReadOnly = true;

   this.textBoxNetName.ReadOnly = true;

   this.comboBoxJobRole.Enabled = false;

   this.comboBoxStatus.Enabled = false;

   this.comboBoxAccess.Enabled = false;

}

Аналогичным образом сформируем метод DisplayEdit, который задает режим редактирования формы:

/// Задание режима редактирования

public void DisplayEdit()

{

   this.textBoxSurname.ReadOnly = false;

   this.textBoxName.ReadOnly = false;

   this.textBoxPatronymic.ReadOnly = false;

   this.textBoxNetName.ReadOnly = false;

   this.comboBoxJobRole.Enabled = true;

   this.comboBoxStatus.Enabled = true;

   this.comboBoxAccess.Enabled = true;

}

Для управления режимом доступности (только для чтения/редактирование) формы FormEmployee необходимо метод DisplayReadOnly вызывать при первоначальной загрузке формы (событие Load ), при создании новых данных по сотруднику и при редактировании данных по сотруднику, а метод DisplayEdit - при сохранении данных по сотруднику и при отмене режима редактирования данных.

Проверьте правильность режима управления доступностью элементов управления формы FormEmployee.

//-

//-

//-

Анализ кодов методов DisplayReadOnly( ) и DisplayEdit( ) показывает, что они могут быть объединены в один метод с параметром. Необходимо самостоятельно написать объединенный метод, получив в результате метод DisplayReadOnly(bool readOnly), в котором параматр readOnly определяет режим редактирования: если readOnly равен true, то режим только для просмотра, если равен false, то - редактирование.

В процессе работы приложения необходимо управлять доступом к пунктам меню в соответствии с диаграммой состояний для пунктов меню формы FormEmployee, приведенной на рисунке 7.10.

Рис. 7.10.  Диаграмма состояний для активности подпунктов меню "Действие"

Диаграмма отображает возможные переходы между тремя режимами: "Просмотр", "Редактирование" и "Создание нового сотрудника".

При выборе в главном меню приложения пункта "Сотрудник" Windows -форма FormEmployee должна перейти в режим "Просмотр", что определяет доступ к пунктам меню "Создать", "Редактировать", "Удалить" и запрет доступа к подпунктам меню "Отменить", "Сохранить".

Если в режиме просмотр выбирается подпункт меню "Удалить", то в результате выполнения данной функции режим Windows-формы FormEmployee не должен измениться, т.е. форма должна остаться в режиме "Просмотр".

Если в режиме просмотр выбирается подпункт меню "Изменить", то Windows-формы FormEmployee должна перейти в режим "Редактирование". Данный режим предполагает, что разрешается доступ к подпунктам меню "Отменить", "Сохранить" и запрещается доступа к подпунктам меню "Создать", "Редактировать", "Удалить".

Аналогичным образом интерпретируются переходы формы FormEmployee из одного режима в другой.

На рисунке 7.10 представлены режимы и переходы для подпунктов главного меню. Аналогичные режимы необходимо соблюдать для контекстного меню и кнопок панели инструментов.

Для управления доступом к пунктам главного меню создайте методы MenuItemEnabled(bool itemEnabled), для контекстного меню - MenuItemContextEnabled(bool itemEnabled) и для кнопок панели управления -StripButtonEnabled(bool itemEnabled). Управление доступностью пунктов главного и контекстного меню осуществляется через свойство Enabled класса ToolStripMenuItem, а кнопок панели управления - через свойство Enabled класса ToolStripButton.

Проверьте правильность режима управления пунктов главного и контекстного меню, а также кнопок панели управления формы FormEmployee.

С учетом того, что установка режимов просмотра и редактирования экранной формы, а также управление доступом к пунктам меню должно выполняться при реализации нескольких функций программы целесообразно для избежания дублирования кода все методы управления режимами объединить в один метод DisplayForm.

private void DisplayForm(bool mode)

{

   DisplayReadOnly(mode);

   MenuItemEnabled(mode);

   MenuItemContextEnabled(mode);

   StripButtonEnabled(mode);

}

Первоначальная установка режима "Просмотр" должна проводиться при первоначальной загрузке формыFormEmployee.

Задание на лабораторную работу

  1.  Изучить теоретический материал.
  2.  Для формы FormEmployee создать требуемые элементы контроля.
  3.  Разработать методы для задания режимов "Просмотр", "Редактирование" для элементов контроля.
  4.  Разработать методы для задания режимов "Просмотр", "Редактирование" для управления активностью пунктов главного меню формы, контекстного меню и кнопок панели инструментов.
  5.  Сформировать обработчик события Load.
  6.  Протестировать программу.

8. Лабораторная работа: Подготовка ADO.NET к работе в приложении

Содержание

  •  Общие сведения
  •  Информация о базе данных
  •  Задание на лабораторную работу

Цель работы: Изучить назначение и основные способы создания объектов ADO.NET при помощи Visual Studio IDE

Общие сведения

В платформе .NET определено множество типов (организованных в соответствующие пространства имен) для взаимодействия с локальными и удаленными хранилищами данных. Общее название пространств имен с этими типами - ADO.NET.

ADO.NET - это новая технология доступа к базам данных, специально оптимизированная для нужд построения рассоединенных ( disconnected ) систем на платформе .NET.

Технология ADO.NET ориентирована на приложения N-tier - архитектуру многоуровневых приложений, которая в настоящее время стала фактическим стандартом для создания распределенных систем.

Основные отличительные особенности ADO.NET:

  •  ADO расширяет концепцию объектов-наборов записей в базе данных новым типом DataSet, который представляет локальную копию сразу множества взаимосвязанных таблиц. При помощи объекта DataSetпользователь может локально производить различные операции с содержимым базы данных, будучи физически рассоединен с СУБД, и после завершения этих операций передавать внесенные изменения в базу данных при помощи соответствующего "адаптера данных" ( data adapter );
  •  в ADO.NET реализована полная поддержка представления данных в XML -совместимых форматах. В ADO.NETсформированные для локальной обработки наборы данных представлены в формате XML (в этом же формате они и передаются с сервера баз данных). Данные в форматах XML очень удобно передавать при помощи обычного HTTP, решает многие проблемы с установлением соединений через брандмауэры;
  •  ADO.NET - это библиотека управляемого кода и взаимодействие с ней производится как с обычной сборкой.NET. Типы ADO.NET используют возможности управления памятью CLR и могут использоваться во многих.NET - совместимых языках. При этом обращение к типам ADO.NET (и их членам) производится практически одинаково вне зависимости от того, какой язык используется.

Все типы ADO.NET предназначены для выполнения единого набора задач:

  •  установить соединение с хранилищем данных;
  •  создать и заполнить данными объект DataSet ;
  •  отключиться от хранилища данных и вернуть изменения, внесенные в объект DataSet обратно в хранилище данных.

Объект DataSet - это тип данных, представляющий локальный набор таблиц и информацию об отношениях между ними.

DataSet - набор связанных таблиц. На практике можно создать на клиенте объект DataSet, который будет представлять полную копию удаленной базы данных.

После создания объекта DataSet и его заполнения данными можно программными средствами производить запросы к нему и перемещаться по таблицам, выполнять все операции, как при работе с обычными базами данных: добавлять в таблицы новые записи, удалять и изменять существующие, применять к ним фильтры и т.п. После того как клиент завершит внесение изменений, информация о них будет отправлена в хранилище данных для обработки.

Создание DataSet осуществляется при помощи управляемого провайдера ( managed provider ).

Управляемый провайдер - это набор классов, реализующих интерфейсы, определенные в пространстве именSystem.Data.

Речь идет об интерфейсах IDbCommandIDbDataAdapterIDbConnection и IDataReader (рисунок 8.1).



Рис. 8.1.  Взаимодействие клиента с управляемыми провайдерами

В состав ADO.NET включены два управляемых провайдера: провайдер SQL и провайдер OleDb. Провайдер SQLспециально оптимизирован под взаимодействие с Microsoft SQL Server версии 7.0 и последующих. Для других источников данных предлагается использовать провайдер OleDb, который можно использовать для обращения к любым хранилищам данных, поддерживающим протокол OLE DB. Следует отметить, что провайдер OleDb работает при помощи "родного" OLE DB и требует возможности взаимодействия при помощи СОМ.

Все возможности ADO.NET заключены в типах, определенных в соответствующих пространствах имен. Краткий обзор главных пространств имен ADO.NET представлен в таблице 8.1.

Таблица 8.1. Пространства имен ADO.NET

Пространство имен

Описание

System.Data

Главное пространство имен ADO.NET. В нем определены типы, представляющие таблицы, столбцы, записи, ограничения и тип - DataSet.

System.Data.Common

Определены типы, общие для всех управляемых провайдеров. Многие из них выступают в качестве базовых классов для классов из пространств имен для провайдеров SQL и OleDb

System.Data.OleDb

В этом пространстве имен определены типы для установления соединений с OLE DB-совместимыми источниками данных, выполнения к ним SQL-запросов и заполнения данными объектов DataSet.

System.Data.SqlCIient

В этом пространстве имен определены типы, которые составляют управляемый провайдер SQL.

System.Data.SqlTypes

Представляют собой "родные" типы данных Microsoft SQL Server.

Все пространства имен ADO.NET расположены в одной сборке - System.Data.dll. Это означает, что в любом проекте, использующем ADO.NET, мы должны добавить ссылку на эту сборку.

В любом приложении ADO.NET необходимо использовать, по крайней мере, одно пространство имен -System.Data. Кроме того, практически во всех ситуациях требуется использовать либо пространство именSystem.Data.OleDb или System.Data.SqlClient - для установления соединения с источником данных.

Типы пространства имен System.Data предназначены для представления данных, полученных из источника (но не для установления соединения непосредственно с источником).

В основном эти типы представляют собой объектные представления примитивов для работы с базами данных - таблицами, строками, столбцами, ограничениями и т. п. Наиболее часто используемые типы System.Dataпредставлены в таблице 8.2.

Таблица 8.2. Типы пространства имен System.Data

Тип

Назначение

DataColumnCollection, DataColumn

DataColumn представляет один столбец в объекте DataTableDataColumnCollection- все столбцы

ConstraintCollection, Constraint

Constraint - объектно-ориентированная оболочка вокруг ограничения (например, внешнего ключа или уникальности), наложенного на один или несколькоDataColumnConstraintCollection - все ограничения в объекте DataTable

DataRowCollection, Data Row

DataRow представляет единственную строку в DataTableDataRowCollection - все строки в DataTable

DataRowView, Data View

DataRowView позволяет создавать настроенное представление единственной строки,DataView - созданное программным образом представление объекта DataTable, которое может быть использовано для сортировки, фильтрации, поиска, редактирования и перемещения

DataSet

Объект, создаваемый в оперативной памяти на клиентском компьютере. DataSetсостоит из множества объектов DataTable и информации об отношениях между ними

ForeignKeyConstraint, UniqueConstraint

ForeignKeyConstraint представляет ограничение, налагаемое на набор столбцов в таблицах, связанных отношениями первичный - внешний ключ. UniqueConstraint - ограничение, при помощи которого гарантируется, что в столбце не будет повторяющихся записей

DataRelationCollection, DataRelation, DataTableCollection, DataTable

Тип DataRelationCollection представляет набор всех отношений (то есть объектовDataRelation ) между таблицами в DataSet. Тип DataTableCollectionпредставляет набор всех таблиц (объектов DataTable ) в DataSet

В традиционных системах клиент-сервер при запуске приложения пользователем автоматически устанавливается связь с базой данных, которая поддерживается в "активном" состоянии до тех пор, пока приложение не будет закрыто. Такой метод работы с данными становится непрактичным, поскольку подобные приложения трудно масштабируются. Например, такая прикладная система может работать достаточно быстро и эффективно при наличии 8-10 пользователей, но она может стать полностью неработоспособной, если с ней начнут работать 100, 200 и более пользователей. Каждое открываемое соединение с базой данных "потребляет" достаточно много системных ресурсов сервера, они становятся занятыми поддержкой и обслуживанием открытых соединений, их не остается на процессы непосредственной обработки данных.

При разработке прикладных систем в сети Интернет ( Web -приложения) необходимо добиваться максимальной масштабируемости. Система должна работать одинаково эффективно как с малым, так и с большим числом пользователей.

По этой причине, в ADO.NET используется модель работы пользователя в отрыве от источника данных. Приложения подключаются к базе данных только на небольшой промежуток времени. Соединение устанавливается только тогда, когда клиент удаленного компьютера запрашивает на сервере данные. После того, как сервер подготовил необходимый набор данных, сформировал и отправил их клиенту в виде WEB -страницы, связь приложения с сервером сразу же обрывается, и клиент просматривает полученную информацию уже не в связи с сервером. При работе в сети Интернет нет необходимости поддерживать постоянную "жизнеспособность" открытых соединений, поскольку неизвестно, будет ли конкретный клиент вообще далее взаимодействовать с источником данных. В таком случае целесообразнее сразу освобождать занимаемые серверные ресурсы, что обеспечит обслуживание большего количества пользователей. Модели доступа к данным представлена на рисунке 8.2.


Рис. 8.2.  Модель доступа к данным в ADO.NET

В объектной модели ADO.NET можно выделить несколько уровней.

Уровень данных. Это по сути дела базовый уровень, на котором располагаются сами данные (например, таблицы базы данных MS SQL Server ). На данном уровне обеспечивается физическое хранение информации на магнитных носителях и манипуляция с данными на уровне исходных таблиц (выборка, сортировка, добавление, удаление, обновление и т. п.).

Уровень бизнес-логики. Это набор объектов, определяющих, с какой базой данных предстоит установить связь и какие действия необходимо будет выполнить с содержащейся в ней информацией. Для установления связи с базами данных используется объект DataConnection. Для хранения команд, выполняющих какие либо действия над данными, используется объект DataAdapter. И, наконец, если выполнялся процесс выборки информации из базы данных, для хранения результатов выборки используется объект DataSet. Объект DataSet представляет собой набор данных "вырезанных" из таблиц основного хранилища, который может быть передан любой программе-клиенту, способной либо отобразить эту информацию конечному пользователю, либо выполнить какие-либо манипуляции с полученными данными.

Уровень приложения. Это набор объектов, позволяющих хранить и отображать данные на компьютере конечного пользователя. Для хранения информации используется уже знакомый нам объект DataSet, а для отображения данных имеется довольно большой набор элементов управления ( DataGrid, TextBox, ComboBox, Label и т. д.). В Visual Studio .Net можно вести разработку двух типов приложений. В первую очередь это традиционныеWindows -приложения (на основе Windows -форм), которые реализованы в виде ехе-файлов, запускаемых на компьютере пользователя. Ну и конечно, Web -приложения (на основе Web -форм), которые работают в оболочке браузера. Как видно из рисунка 8.2, для хранения данных на уровне обоих типов приложений используется объект DataSet.

Обмен данными между приложениями и уровнем бизнес-логики происходит с использованием формата XML, а средой передачи данных служат либо локальная сеть (Интранет), либо глобальная сеть (Интернет).

В ADO.NET для манипуляции с данными могут использоваться команды, реализованные в виде SQL -запросов или хранимых процедур ( DataCommand ). Например, если необходимо получить некий набор информации базы данных, вы формируете команду SELECT или вызываете хранимую процедуру по ее имени.

Когда требуется получить набор строк из базы данных, необходимо выполнить следующую последовательность действий:

  •  открыть соединение ( connection ) с базой данных;
  •  вызвать на исполнение метод или команду, указав ей в качестве параметра текст SQL -запроса или имя хранимой процедуры;
  •  закрыть соединение с базой данных.

Связь с базой данных остается активной только на достаточно короткий срок - на период выполнения запроса или хранимой процедуры.

Когда команда вызывается на исполнение, она возвращает либо данные, либо код ошибки. Если в команде содержался SQL -запрос на выборку - SELECT, то команда может вернуть набор данных. Вы можете выбрать из базы данных только определенные строки и колонки, используя объект DataReader, который работает достаточно быстро, поскольку использует курсоры read-only, forward-only.

Если требуется выполнить более чем одну операцию с данными, например, получить некоторый набор данных, а затем скорректировать его, - то необходимо выполнить последовательность команд. Каждая команда выполняется отдельно, последовательно одна за другой. Между выполняемыми командами соединение с базой отсутствует. Например, чтобы получить данные из базы - открывается связь, выбираются данные, затем связь закрывается. Когда выполняется обновление базы после корректировки информации пользователем, снова открывается связь, выполняется обновление данных в исходных таблицах и связь снова закрывается.

Команды работы с данными могут содержать параметры, т. е. могут использоваться параметризированные запросы, как, например, следующий запрос:

SELECT * FROM customers WHERE (customer_id=@customerid)

Значения параметров могут задаваться динамически, во время выполнения приложения.

Как правило, в приложениях необходимо извлечь информацию из базы данных и выполнить с ней некоторые действия: показать пользователю на экране монитора, сделать нужные расчеты или послать данные в другой компонент. Очень часто, в приложении нужно обработать не одну запись, а их набор: список клиентов, перечень заказов, набор элементов заказа и т. п. Как правило, в приложениях требуется одновременная работа с более чем одной таблицей: клиенты и все их заказы; автор и все его книги, заказ и его элементы, т.е. с набором связанных данных. Причем для удобства пользователя данные требуется группировать и сортировать то по одному, то по другому признаку. При этом нерационально каждый раз возвращаться к исходной базе данных и заново считывать данные. Более практично работать с некой временной "вырезкой" информации, хранящейся в оперативной памяти компьютера.

Эту роль выполняет набор данных - DataSet, который представляет собой своеобразный кэш записей, извлеченных из базового источника. DataSet может состоять из одной или более таблиц, он имеет дело с копиями таблиц из базы данных источника. Кроме того, в данном объекте могут содержаться связи между таблицами и некоторые ограничения на выбираемые данные. Структура объекта DataSet приведена на рисунке 8.3.


Рис. 8.3.  Структура объекта DataSet

Данные в DataSet - это некий уменьшенный вариант основной базы данных. Тем не менее, вы можете работать с такой "вырезкой" точно так же, как и с реальной базой. Поскольку каждый пользователь манипулирует с полученной порцией информации, оставаясь отсоединенными от основной базы данных, последняя может в это время решать другие задачи.

Конечно, практически в любой задаче обработки данных требуется корректировать информацию в базе данных (хотя и не так часто, как извлекать данные из нее). Вы можете выполнить операции коррекции непосредственно в DataSet, a потом все внесенные изменения будут переданы в основную базу данных.

Важно отметить то, что DataSet - пассивный контейнер для данных, который обеспечивает только их хранение. Что же нужно поместить в этот контейнер, определяется в другом объекте - адаптере данных DataAdapter. В адаптере данных содержатся одна или более команд, которые определяют, какую информацию нужно поместить в таблицы объекта DataSet, по каким правилам нужно синхронизировать информацию в конкретной таблицеDataSet и соответствующей таблицей основной базы данных и т. п. Адаптер данных обычно содержит четыре команды SELECT, INSERT, UPDATE, DELETE, для выборки, добавления, корректировки и удаления записей.

Например, метод Fill объекта DataAdapter, заполняющего данными контейнер DataSet, может использовать в элементе SelectCommand следующий запрос:

SELECT au_id, au_lname, au_fname FROM authors

Набор данных DataSet - "независимая" копия фрагмента базы данных, расположенная на компьютере пользователя. Причем в этой копии могут быть не отражены те изменения, которые могли внести в основную базу данных другие пользователи. Если требуется увидеть самые последние изменения, сделанные другими пользователями, то необходимо "освежить" DataSet, повторно вызвав метод Fill адаптера данных.

Информация о базе данных

Разрабатываемое приложение предназначено для работы с базой данных сотрудников компании. На рисунке 8.4 представлена структура базы данных.


Рис. 8.4.  Структура базы данных по сотрудникам компании

База данных включает две таблицы:

  •  сведения о сотрудниках - Employee ;
  •  справочник должностей - JobTitle.

Назначение атрибутов таблицы Employee приведены в таблице 8.4

Таблица 8.4. Атрибуты таблицы Employee

Имя атрибута

Назначение

Тип

EmployeeID

Суррогатный ключ

smallint

JobRoleID

Внешний ключ

smallint

EmployeeSurname

Фамилия

varchar(50)

EmployeeName

Имя

varchar(20)

EmployeePatronymic

Отчество

varchar(20)

EmployeeStatus

Статус

int

Access

Уровень доступа

varchar(20)

NetName

Сетевое имя

varchar(20)

Birthday

Дата рождения

Smalldatetime

FirstDate

Дата приема на работу

smalldatetime

Суррогатный ключ EmployeeID, как и все остальные суррогатные ключи базы данных, генерируется сервером базы данных автоматически, т.е. для него задано свойство IDENTITY для СУБД MS SQL Server или AutoNumberдля MS Access. Атрибут JobRoleID является внешним ключом, с помощью которого осуществляется связь с таблицей JobTitle.

Назначение атрибутов таблицы JobTitle приведено в таблице 8.3.

Таблица 8.3. Атрибуты таблицы JobTitle

Имя атрибута

Назначение

Тип

JobRoleID

Суррогатный ключ

smallint

JobRoleName

Наименование должности

varchar(50)

В рассматриваемом приложении в качестве СУБД используется MS SQL Server 2005. Создаем соединение проекта с базой данных. Для этого выбираем пункт меню Tools/Connect to Database. Появляется окноAddConnection (рисунок 8.5)


Рис. 8.5.  Окно AddConnection

В пункте "Server name" задаем имя сервера, которое необходимо узнать у преподавателя (на рисунке 8.5 MYHOME-8834E210\DOLJENKO ). В пункте Select or enter database name - имя базы данных, которое определит преподаватель (на рисунке 8.5 - Employee ).

Для проверки правильности подключения к базе данных нажимаем клавишу "Test Connection". При правильном подключении появляется следующее сообщение (рисунок 8.6).


Рис. 8.6.  Окно Microsoft Data Link

При нормальном соединении с базой данных можно открыть навигатор Server Explorer из меню View/ Server Explorer или сочетанием клавиш ALT+CTRL+S (рисунок 8.7).


Рис. 8.7.  Окно навигатора Server Explorer

Добавим в проект объект класса DataSet. Для этого выберем пункт меню Project/Add New Item. . . (рисунок 8.8).


Рис. 8.8.  Добавление в проект нового компонента

В окне Add New Item (рисунок 8.9) выберем шаблон DataSet и присвоим ему имя DataSetEmployee.


Рис. 8.9.  Выбор нового компонента - DataSet

После нажатия кнопки Add система генерирует класс DataSetEmployee, который добавляется в решение проекта (рисунок 8.10).


Рис. 8.10.  Окно решения проекта с новым компонентом DataSet

Для добавления таблиц Employee и JobTitle к DataSet необходимо перетащить их из окна Server Explorer на поле графического дизайнера (рисунок 8.11).


Рис. 8.11.  Добавление таблиц к DataSet

В результате будут созданы классы таблиц, адаптеры и методы Fill и GetData.

При формировании класса DataSetEmployee необходимо учесть то, что первичные ключи таблиц Employee иJobTitle являются суррогатными и автоматически формируются (ключ со свойством автоинкремент) источником данных (например, MS SQL Server ). При формировании новых записей в приложении необходимо обеспечить уникальность первичных ключей для таблиц объекта DataSetEmployee. Это можно обеспечить, задав для ключевых колонок таблиц Employee и JobTitle следующие свойства:

AutoIncrement = true;

AutoIncrementSeed = -1;

AutoIncrementStep = -1;

Столбец со свойством AutoIncrement равным true генерирует последовательность значений, начинающуюся со значения AutoIncrementSeed и имеющую шаг AutoIncrementStep. Это позволяет генерировать уникальные значения целочисленного столбца первичного ключа. В этом случае при добавлении новой записи в таблицу будет генерироваться новое значение первичного ключа, начиная с -1, -2, -3 и т.д., которое никогда не совпадет с первичным ключом источника данных, т.к. в базе данных генерируются положительные первичные ключи. Свойства AutoIncrementSeed и AutoIncrementStep устанавливаются равными -1, чтобы гарантировать, что когда набор данных будет синхронизироваться с источником данных, эти значения не будут конфликтовать со значениями первичного ключа в источнике данных. При синхронизации DataSet с источником данных, когда добавляют новую строку в таблицу MS SQL Server 2005 с первичным автоинкрементным ключом, значение, которое этот ключ имел в таблице DataSet, заменяется значением, сгенерированным СУБД.

Установка свойств AutoIncrementAutoIncrementSeed и AutoIncrementStep для колонки первичного ключаEmployeeID таблицы Employee приведена на рисунке 8.12.


Рис. 8.12.  Установка свойств для колонки EmployeeID

Аналогичные установки свойств AutoIncrementAutoIncrementSeed и AutoIncrementStep необходимо сделать и для колонки JobTitleID таблицы JobTitle.

После создания класса DataSetEmployee и адаптера необходимо создать объекты этих классов, добавив следующий код к файлу FormEmployee.cs.

DataSetEmployee dsEmployee = new DataSetEmployee();

DataSetEmployeeTableAdapters.EmployeeTableAdapter daEmployee =

  new Project_К4И_01.DataSetEmployeeTableAdapters.

EmployeeTableAdapter();

DataSetEmployeeTableAdapters.JobTitleTableAdapter daJobTitle =

 new Project_К4И_01.DataSetEmployeeTableAdapters.

JobTitleTableAdapter();

После того, как созданы объекты адаптеров данных daEmployee и daJobTitle, а также объект классаDataSetEmployee - dsEmployee необходимо создать метод для заполнения объекта dsEmployee из базы данных (в рассматриваемом примере база данных Employee, созданная в СУБД MS SQL Server 2005 ). Для заполнения данными dsEmployee из базы данных Employee создадим метод EmployeeFill( ):

public void EmployeeFill()

{   daJobTitle.Fill(dsEmployee.JobTitle);

   daEmployee.Fill(dsEmployee.Employee);

   MessageBox.Show("Метод Fill отработал");}

В методе EmployeeFill( ) для объектов класса DataAdapter применяется метод Fill, который производит заполнение таблиц ( JobTitle и Employee ) объекта dsEmployee данными из базы данных. Метод Fill адаптера данных DataAdapter требует указания в качестве параметров задания соответствующей таблицы DataSet, то есть dsEmployee.JobTitle и dsEmployee.Employee.

Метод MessageBox.Show введен в метод EmployeeFill для первоначального тестирования, после которого его нужно убрать.

Вызов метода EmployeeFill необходимо добавить в обработчик события Load для формы FormEmployee, возникающего при нажатии на пункт меню "Сотрудник".

Задание на лабораторную работу

  1.  Изучите теоретический материал.
  2.  Создайте класс DataSetEmployee.
  3.  Для разрабатываемого приложения создайте объекты dsEmployeedaJobTitle и daEmployee.
  4.  Проведите компиляцию проекта и убедитесь в отсутствии ошибок трансляции.
  5.  Разработайте метод Fill для заполнение таблиц DataSet.
  6.  Протестировать работу приложения.

9. Лабораторная работа: Отображение данных на экранной форме

Содержание

  •  Основные сведения
  •  Задание на лабораторную работу

Цель работы: Изучить основные приемы и способы отображения и связывания данных объекта DataSet и элементов управления Windows- формы.

Основные сведения

Для отображения информации на элементах управления Windows Forms необходимо осуществить их заполнение из соответствующих столбцов и строк таблиц DataSet. Это можно сделать путем написания специального кода, который предназначен для заполнения соответствующих элементов управления или использовать механизм привязки данных к пользовательским интерфейсам .NET.

Windows Forms позволяют отображать данные путем привязки их элементов управления к источникам данных. Привязка данных обычно используется для отображения результатов поиска, детализации сводок, генерации отчетов и ввода данных. Существует два типа привязки данных: простая и сложная. В случае простой привязки данных элемент управления привязывается к отдельному элементу данных. Простая привязка, в основном, используется с такими элементами управления, как поле ввода ( TextBox ) и надпись ( Lable ). При сложной привязке данных элемент управления привязывается более чем к одному элементу данных - обычно к одному или нескольким столбцам в нескольких строках результирующего набора строк. К элементам управления, поддерживающим сложную привязку данных, относятся список ( ListBox ), выпадающий список ( ComboBox ), список данных ( DataList ) и табличный элемент ( DataGrid ).

В технологии привязки элементов управления Windows Forms используется абстрактный классBindingManagerBase. Данный класс синхронизирует все элементы управления Windows Forms (т. е. объектыBinding ), привязанные к одному источнику данных, позволяя отображать информацию об объекте в источнике данных - например, о строке в локальной таблице.

Класс BindingContext используется для создания экземпляра объекта BindingManagerBase, и возвращается при этом объект CurrencyManager или PropertyManager в зависимости от типа источника данных:

Класс CurrencyManager является потомком класса BindingManagerBase и поддерживает указатель на текущий элемент в источнике данных, который реализует интерфейсы IListIListSource или IBindingList. Источники данных не обязательно поддерживают указатель на текущий элемент. CurrencyManager уведомляет все привязанные элементы управления об изменении текущего элемента, чтобы они могли обновить свои данные. Класс CurrencyManager поддерживает текущее свойство объекта, а не сам объект в списке.

Свойство Position - это индекс с отсчетом от нуля, позволяющий узнать или задать текущую позицию в источнике данных. Свойство Count возвращает количество элементов данных в списке. Свойство Currentвозвращает текущий объект в списке, который необходимо привести к типу объекта в соответствующем источнике данных, прежде чем с ним можно будет работать.

При связывании элемента контроля ListBox устанавливается множественная связь с источником данных. Для связи используются свойства списка DataSource и DisplayMember. Свяжем элемент контроля listBoxEmployee, в котором должен отображаться список фамилий сотрудников, со столбцом EmployeeSurname таблицы Employee. Это можно сделать, добавив следующие строки кода в метод загрузки формы FormEmployee_Load.

this.listBoxEmployee.DataSource = this.dsEmployee;

this.listBoxEmployee.DisplayMember =

           "Employee.EmployeeSurname";

Протестируйте добавленный в программу код.

В разрабатываемом приложении на Windows -форме FormEmployee имеются четыре текстовых поля:textBoxSurnametextBoxNametextBoxPatronymic и textBoxNetName. Эти текстовые поля предназначены для отображения информации из одной записи таблицы Employee набора данных dsEmployee. Для того чтобы содержимое текстовых полей автоматически обновлялось при смене записи, их необходимо связать с соответствующими колонками набора данных dsEmployee. Связывание можно осуществить, используя свойствоDataBindings элемента управления TextBox. Например, для элемента управления textBoxSurname можно осуществить связь с источником данных, добавив следующую строку кода в метод загрузки формыFormEmployee_Load.

textBoxSurname.DataBindings.Add("Text", dsEmployee,

"Employee.EmployeeSurname");

Протестируйте добавленный в программу код.

Аналогично свяжите текстовые поля textBoxNametextBoxPatronymic и textBoxNetName с источником данных.

Протестируйте добавленный в программу код.

В таблице Employee значения для атрибута Access (доступ) задается в виде символьной строки, значение которой выбирается из списка элемента управления comboBoxAccess. Коллекцию выпадающего списка элемента управления comboBoxAccess можно задать следующей строкой кода:

this.comboBoxAccess.Items.AddRange(new object[] {"не задан", "администратор",

 "начальник смены", "старший оператор", "оператор", "аналитик"});

Для заданной записи источника данных (таблица Employee ) значение столбца Access необходимо отобразить в элементе контроля comboBoxAccess. Это можно сделать аналогично тому, как это делалось для элементов управления TextBox, задавая свойство DataBindings

Протестируйте добавленный в программу код.

Для элемента управления comboBoxStatus необходимо сформировать коллекцию выпадающего списка: не задан, активен, выходной, в отпуске, болеет, не работает, помечен как удаленный.

В таблице Employee значения для атрибута EmployeeStatus (статус) задается в виде целого числа ( 0, 1, 2, 3, 4, 6 ), однако статус сотрудника должен отображаться в элементе управления comboBoxStatus в виде строковых значений в соответствии со значениями его коллекции. В программе необходимо реализовать отображение целочисленных данных из DataSet в текстовые значения в элементе контроля comboBoxStatus. Для этого необходимо отслеживать изменение позиции в таблице источника данных dsEmployee и в соответствии со значением столбца EmployeeStatus активизировать требуемый элемент ( Item ) спискаcomboBoxStatus.

Объявим объект bmEmployee класса BindingManagerBase в форме FormEmployee:

BindingManagerBase  bmEmployee;

В конструкторе класса FormEmployee, создадим объект bmEmployee применяя индексатор контентаBindingContext включив в него связывание с таблицей Employee и добавим делегат для события, которое формируется при изменении позиции в данной таблице:

public FormEmployee( )

{

InitializeComponent();

bmEmployee = this.BindingContext[dsEmployee, "Employee"];

// Добавляем делегата  PositionChanged для события - изменение

//позиции в таблице Employee DataSet dsEmployee

bmEmployee.PositionChanged += new EventHandler(BindingManagerBase_PositionChanged);

}

Кроме того, необходимо создать обработчик для сформированного события, который на основе выбранной строки ( pos ) таблицы Employee будет задавать свойству Text списка comboBoxStatus значение из коллекцииItems по индексу ( sel ), полученному из столбца EmployeeStatus Employee.

private void BindingManagerBase_PositionChanged(object sender, EventArgs e)

{

int pos = ((BindingManagerBase)sender).Position;

int sel = (int)dsEmployee.Employee[pos].EmployeeStatus;

this.comboBoxStatus.Text = this.comboBoxStatus.Items[sel].ToString();

}

Протестируйте добавленный в программу код.

Для задания в элементе контроля comboBoxJobRole должности сотрудника необходимо получить данные из родительской таблицы JobTitle, с которой таблица Employee связана внешним ключом JobRoleID. Фактически необходимо осуществить вывод данных из справочника (таблица JobTitle ) по данным в основной таблицеEmployee.

В Windows Forms элемент управления ComboBox имеет три свойства, управляющих привязкой к источникам данных. Эти свойства описаны в таблице 9.1.

Таблица 9.1. Свойства элемента управления ComboBox, управляющие привязкой к источникам данных

Свойство

Описание

Data Source

Позволяет узнать или задать источник данных для элемента управления. Это может быть объектData TableDataView или вообще любой объект, реализующий интерфейс IList

DisplayMember

Позволяет узнать или задать свойство источника данных, которое отображается в элементе управления. В случае DataTable и DataView это имя столбца

ValueMember

Позволяет узнать или задать свойство источника данных, которое предоставляет значения для элемента управления. В случае DataTable и DataView это имя столбца. По умолчанию задана пустая строка

Свойство DataBindings объекта ComboBox предоставляет доступ к коллекции ControlBindingsCollection. Метод Add этой коллекции добавляет в неё привязку. Перегруженный вариант метода Add принимает три аргумента:

  •  PropertyName - имя свойства элемента управления, к которому осуществляется привязка;
  •  DataSource - имя привязываемого источника данных;
  •  DataMember - имя свойства привязываемого источника данных.

Вначале связываем элемент контроля comboBoxJobRole с набором данных JobTitle (родительская таблица - справочник), в соответствии с кодом, приведенным ниже.

comboBoxJobRole.DataSource = this.dsEmployee.JobTitle;

comboBoxJobRole.DisplayMember = "JobRoleName";

comboBoxJobRole.ValueMember = "JobRoleID";

После этого необходимо связать comboBoxJobRole с полем JobRoleID основной таблицы Employee (дочерняя таблица), в соответствии со следующим кодом

comboBoxJobRole.DataBindings.Add("SelectedValue", dsEmployee,"Employee.JobRoleID");

После компиляции и запуска приложения экранная форма будет иметь вид, приведенный на рисунке 9.1.


Рис. 9.1.  Экранная форма в режиме просмотра (только для чтения)

Задание на лабораторную работу

  1.  Изучите теоретический материал.
  2.  Осуществите привязку источника данных к элементам управления экранной формы.
  3.  Разработайте необходимые методы для вывода информации из базы данных на экранную форму.
  4.  Протестируйте приложение

10. Лабораторная работа: Модификация, вставка и удаление записей в наборе данных

Содержание

  •  Основные концепции обновления наборов данных в Microsoft .NET
  •  Модификация, вставка и удаление записей в наборе данных
  •  Модификация данных
  •  Сохранение данных
  •  Добавление данных
  •  Удаление данных
  •  Отмена изменений
  •  Задание на лабораторную работу

Цель работы: Изучить основные приемы и способы заполнения объекта DataSet, работы с записями набора данных

Основные концепции обновления наборов данных в Microsoft .NET

Когда в приложении пользователь работает с наборами данных DataSet, то фактически он оперирует с записями, оторванными от основной базы и находящимися в памяти компьютера. При такой модели доступа к данным возникает необходимость периодического обновления информации, содержащейся в основной базе данных. Когда пользователь вносит какие-либо изменения в записи таблицы объекта DataSet, то DataSetотслеживает и запоминает все эти изменения. По мере необходимости все сделанные изменения можно вернуть источнику данных. В течение процесса обновления источника данных происходит несколько событий, которые можно использовать для проверки правильности введенной пользователем информации.

Поскольку набор данных это фактически набор записей, оторванных от основной базы и помещенных в оперативную память компьютера, то процесс возврата изменений первоначальному источнику данных является изолированной процедурой и отделен от процесса модификации данных в DataSet.

Модификация источника данных через набор данных происходит в два этапа. На первом этапе модифицируется сам набор данных: пользователь добавляет новые записи, изменяет или удаляет существующие. Все эти процессы происходят в копии, оторванной от основного источника данных. На втором шаге необходимо послать эти изменения от оторванного набора данных к первоначальному источнику данных. То есть все изменения в наборе данных не передаются к основному источнику данных автоматически, этот процесс нужного активизировать явно. Это обычно достигается путем вызова метод Update адаптера данных.

На рисунке 10.1 приведен иллюстративный пример обновления полей EmployeeSurname и EmployeeName таблицыEmployee в соответствии с двухступенчатой схемой обновления данных в DataSet.


Рис. 10.1.  Схема двухступенчатого обновления данных в DataSet

Информация в объекте DataSet доступна через его коллекции. Набор данных содержит коллекцию таблиц (DataTable ). Таблица содержат коллекции строк ( DataRow ). Строка содержит коллекцию колонок (DataColumn ). Внесение изменений в наборе данных происходит путем навигации по элементам коллекции и модификации значений конкретных колонок. В объекте DataSet имеется набор методов, которые позволяют модифицировать только сам набор записей (их используют тогда, когда заведомо известно, что обновления не будут передаваться источнику данных). И есть набор методов, которые позволяют обновить информацию, как в наборе данных, так и в источнике данных.

Например, чтобы удалить записи из таблицы можно вызвать метод RemoveAt коллекции ROWS таблицы данных, которая физически удаляет записи из набора данных. Если набор данных используется только как элемент для отображения информации, и не предполагается возвращать изменения источнику данных или передавать другому приложению, то это наиболее оптимальный путь.

Однако если необходимо послать изменения источнику данных или другому приложению, то нужно фиксировать (запоминать) все изменения, которые были сделаны в DataSet. Затем, когда потребуется переслать изменения источнику данных, необходимо будет знать, какие записи были изменены в объекте DataSet и как их найти в источнике данных. Например, если удаляется запись в наборе данных, то нужно запомнить ключевую информацию об этой записи, а затем, когда будет вызван метод адаптера данных DeleteCommand, то ему должны быть переданы параметры удаленной записи, чтобы он смог определить местонахождение аналогичной записи в источнике данных и удалить именно ее.

Когда выполняется модификация записи, то пользователь поочередно изменяет значения отдельных столбцов. Если набор данных содержит ограничения (типа внешних ключей или запрещения присвоения значения null ), возможно, что вся запись может временно находиться в состоянии ошибки, поскольку пользователь не может одновременно присвоить или изменить значения всех столбцов.

Чтобы предотвратить преждевременное нарушение работы программы, можно временно приостановить действие ограничений обновления. Такое действие преследует две цели:

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

После того, как пользователь завершил обновление всех колонок записи, можно вновь включить действие ограничений.

Когда происходит модификация записи в наборе данных, то могут возникнуть ошибки. Например, столбцу может быть присвоено значение, которое имеет несоответствующий тип данных, превышает допустимую размерность, нарушается целостность данных и т. п. Для предотвращения сбоя работы приложения при возникновении ошибочных ситуаций имеется возможность проверки правильности вводимой информации на любой стадии обновления данных.

Информация об изменениях в наборе данных поддержана двумя способами: наличие в каждой строке признака, указывающего на факт внесения изменения в строку ( RowState ), сохранение нескольких копий (версий) строки ( DataRowVersion ). На основе этой информации можно однозначно определить, что изменялось в наборе данных и куда адресовать эти изменения в источнике данных.

Объект DataRow имеет свойство DataRowState, в котором хранится информация о состоянии строки данных. В таблице 10.1 приведены возможные значения свойства DataRowState.

Таблица 10.1. Значения свойства DataRowState объекта DataRow

Значение свойства

Описание

Added

Строка была добавлена к коллекции строк DataRowCollection (для этой строки существует только текущая версия в наборе данных и отсутствует соответствующая оригинальная версия). Ее не было в наборе данных на момент последнего вызова метода AcceptChanges

Deleted

Строка была удалена использованием метода DataRow.Delete объекта DataRow

Detached

Строка была создана, но еще не является элементом коллекции DataRowCollection. ОбъектDataRow находится в этом состоянии сразу после того, как был создан, но еще не добавлен к коллекции, или если он был специально удален из коллекции

Modified

Значение столбца в строке было изменено

Unchanged

Строка не изменялась с тех пор, как был вызван метод AcceptChanges

Наборы данных поддерживают множественные версии записей. Объект DataRow имеет свойство DataRowVersion, в котором хранится информации о версии каждой строки. В таблице 10.2 приведены возможные значения свойства DataRowVersion.

Первоначальная (оригинальная) и текущая версии записей используются тогда, когда требуется вернуть изменения источнику данных. Как правило, когда изменения посылаются источнику данных, то все обновления, которые требуется передать базе данных, находятся в текущей версии записи, а информация из первоначальной (оригинальной) версии используется для того, чтобы определить местонахождение записи, которую нужно модернизировать в таблице источника данных.

Таблица 10.2. Значения свойства DataRowVersion объекта DataRow

Значение свойства

Описание

Current

Текущая версия записи. В этой строке содержатся все изменения, выполненные с момента последнего вызова метода AcceptChanges. Если строка была удалена, то у нее нет текущей версии

Default

Значение по умолчанию (как определено схемой набора данных или источником данных)

Original

Первоначальная (оригинальная) версия записи. Состояние записи до того, как в нее были внесены какие-либо изменения. Практически эта та версия записи, которая была получена от источника данных

Proposed

Промежуточная версия записей, которая существует временно (в режиме внесения в нее изменений). То есть она существует в промежуток времени между вызовами методов начала редактирования ( BeginEdit ) и завершением редактирования ( EndEdit ). Вы можете обратиться к этой версии записи в обработчике события RowChanging. Вызов метода CancelEdit полностью отменит все внесенные в строку изменения и удалит промежуточную версию строки данных

Например, если пользователь изменил значение первичного ключа записи, то в этом случае, если не сохранить оригинальную запись, будет просто невозможно определить местонахождение соответствующей записи в источнике данных, чтобы выполнить в ней замену модифицированных пользователем колонок. Перед инициализацией процедуры обновления можно сравнить первоначальную (оригинальную) версию записи с записью в источнике данных, чтобы определить, вносил ли в нее кто-нибудь изменения с тех пор, как она была загружена в набор данных.

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

Первоначальная (оригинальная) или текущая версия строки существуют не всегда. Например, когда в таблицу набора данных добавляется новая строка, то первоначальной версии не существует, поскольку этой строки еще нет в источнике данных (существует только текущая версия). Точно так же, если строка была удалена с использованием метода Delete, то остается только первоначальная версия строки, текущая версия отсутствует.

Для проверки существования определенной версии записи можно использовать свойство строки данных HasVersion. Из программы можно обратиться к любой версии записи, передавая значение DataRowVersion как дополнительный параметр при обращении к значению столбца.

Обычно при работе с приложением модифицируются не все записи в наборе данных. Наборы данных и таблицы данных поддерживают метод GetChanges, что позволяет возвратить только те строки, в которые вносились изменения.

Можно создать любые подмножества измененных записей, используя метод GetChanges для любой таблицы данных ( DataTable.GetChanges ) или для всего набора данных ( Dataset.GetChanges ). Если был вызван метод для таблицы данных, то в результате его работы будет возвращена копия таблицы только с измененными записями. Точно так же, если был вызван метод для набора данных, то будет сформирован новый набор данных только с измененными записями этого набора. Вызов метода GetChanges без указания статуса строк, позволит получить все измененные записи. Если методу GetChanges передать в качестве параметра статус строки (DataRowState ), тогда можно получить нужное подмножество измененных записей: только добавленные записи, записи, отмеченные для удаления, отдельные записи (не являющиеся элементами коллекции строк), модифицированные записи.

Получение подмножества измененных записей особенно полезно тогда, когда требуется переслать записи другому компоненту программы для дополнительной обработки. Вместо того чтобы посылать полный набор данных, можно передать только те записи, которые нуждаются в дополнительной обработке, тем самым уменьшить поток передаваемой между компонентами информации.

В процессе появления изменений в наборе данных, изменяется и свойство RowState для отдельных записей. В приложении можно обеспечить доступ, как к первоначальным, так и к текущим версиям записей, используя свойство RowVersion.

Если все изменения, внесенные пользователем в набор данных, переданы источнику данных, то после этого нет необходимости поддерживать информацию о статусе и версиях записей. Как правило, есть два события, после которых набор данных и источник данных находятся в полностью синхронизированном состоянии:

  •  сразу после того, как информация была загружена из источника данных в набор данных;
  •  после передачи всех изменений от набора данных до источника данных.

Можно завершить поддержку обработки изменений набора данных, вызвав метод AcceptChanges (принять изменения). Как правило, метод AcceptChanges вызывается в приложении в двух случаях:

  •  после загрузки набора данных. Если набор данных был загружен путем вызова метода Fill в адаптер данных, то адаптер данных автоматически завершает процедуру поддержки изменений;
  •  после того, как изменения в наборе данных были пересланы другому процессу, типа XML Web-service.

Работа метода AcceptChanges приводит к следующему результату:

  •  значения колонок текущей ( current ) версии записей переносятся в колонки первоначальной ( original ) версии записей (поверх имеющихся там данных);
  •  удаляются все строки, свойство которых RowState имеет значение Deleted ;
  •  свойству всех записей RowState присваивается значение Unchanged.

Метод AcceptChanges доступен на трех уровнях. Можно вызвать данный метод для строки (для объекта DataRow), но тогда завершаются изменения только в одной строке. Можно также вызвать этот метод для таблицы (для объекта DataTable ), в результате чего изменения будут зафиксированы во всех строках таблицы. И, наконец, метод можно применить ко всему набору данных (для объекта DataSet ), вследствие чего будут завершены все изменения во всех записях всех таблиц набора данных.

В таблице 10.3 показано, какие изменения будут завершены в зависимости от того, к какому объекту адресован метод AcceptChanges.

Таблица 10.3. Результат работы метода AcceptChanges

Метод

Результат работы метода

DataRow.AcceptChanges

Завершение изменений только в определенной строке

DataTable.AcceptChanges

Завершение изменений во всех строках определенной таблицы

DataSet.AcceptChanges

Завершение изменений во всех строках, во всех таблицах набора данных

С методом AcceptChanges связан другой метод - RejectChanges, который выполняет противоположное действие - отменяет все изменения. При вызове метода RejectChanges происходит копирование столбцов строки первоначальной версии в строку текущей версии, а свойству RowState каждой записи присваивается значение Unchanged.

Модификация, вставка и удаление записей в наборе данных

После того, как объект DataSet заполнен данными, пользователи приложения обычно модифицируют полученную информацию, и затем эти изменения пересылаются источнику данных. Так как отдельные записи вDataSet представлены объектом DataRow, то все изменения в набор данных производятся путем модификации, добавления и удаления индивидуальных строк.

Чтобы выполнить редактирование какого-либо значения в наборе данных, необходимо обратиться к конкретному столбцу в определенной строке. К определенному значению в наборе данных можно обратиться следующим образом:

  •  через индексы таблиц, строк и коллекций столбцов;
  •  передавая в соответствующие коллекции наименования таблиц и столбцов как строковые переменные.

Модифицирование записей в типизированных и нетипизированных наборах данных осуществляется различными способами.

Наименования таблиц и столбцов в наборах данных без контроля типов (нетипизированные наборы) не доступны во времени разработки приложения и к ним нужно обращаться через их соответствующие индексы.

В типизированных наборах данных используется раннее связывание, за счет чего имена таблиц и столбцов доступны на этапе разработки приложения. Это позволяет создавать более удобочитаемый программный код. В следующем примере показано, как можно модифицировать данные в столбцах JobRoleID и EmployeeSurnameпятой записи таблицы Employee в наборе данных dsEmployee1.

dsEmployee1.Employee[4].JobRoleID = 2;

dsEmployee1.Employee[4].EmployeeSurname = "Иванова";

Для добавление записей в набор данных необходимо создать новую строку и добавить ее к коллекции DataRowсоответствующей таблицы. Следующий пример показывает, как вставить дополнительные строки в объектDataTable - Employee набора данных dsEmployee.

Добавление записи в набор данных происходит следующим образом.

  1.  Вызовите метод таблицы данных NewRow, который создает новую пустую запись. Эта новая запись наследует коллекцию столбцов DataColumnCollection от исходной таблицы данных Employee.

DataRow employeeRow = Employee.NewRow( );

  1.  Присвойте колонкам этой строки требуемые значения .
  2.  employeeRow[JobRoleID] = 1;
  3.  employeeRow[EmployeeSurname] = "Ларина";
  4.  employeeRow[EmployeeName] = "Татьяна";

employeeRow[EmployeePatronymic] = "Ивановна";

  1.  Добавьте новую запись в таблицу, вызвав метод Add объекта

dsEmployee.Employee.Rows.Add(employeeRow);

Удаление записей из набора данных. Если в приложении после удаления записи в наборе данных требуется сделать то же самое и в источнике данных, то необходимо использовать метод Delete таблицы данных. Если ваше приложение не должно пересылать обновления назад источнику данных, тогда возможно прямое удаление записи из коллекции строк.

Для удаления записи из таблицы данных вызовите метод Delete. Этот метод физически не удаляет запись из набора данных; он просто меняет ее статус - отмечает как удаленную запись, и она становится невидимой (перестает быть доступной конечному пользователю приложения).

Следующий пример показывает, как вызвать метод Delete для удаления первой строки таблицы Employee набора данных dsEmployee:

dsEmployee.Employee.Rows[0].Delete( );

Когда происходит обновление (модификация) записей, то в объекте DataTable активизируются определенные события, в обработчике которых можно запрограммировать требуемые действия как до, так и после обновления записи.

Завершение изменений в наборе данных. В наборе данных при внесении изменений в записи (обновление, вставка, удаление) поддерживается и первоначальная (оригинальная), и текущая версии записей. Кроме того, в свойстве RowState каждой записи установлен признак (указатель), находятся ли запись в первоначальном состоянии или она была изменена. Эта информация необходима, когда требуется найти определенную версию строки. Как правило, в приложениях возникает необходимость передачи между компонентами только измененных записей. После того, как проведена нужная обработка всех измененных записей, можно завершить процедуру обновления, вызвав метод набора данных AcceptChanges.

Следующий пример показывает, как вызвать метод AcceptChanges для завершения изменений в таблице Employeeпосле передачи обновлений источнику данных.

daEmployee.Update(dsEmployee, "Employee");

dsEmployee.Employee.AcceptChanges( );

Обновление баз данных из наборов данных. После того, как были сделаны изменения в наборе данных, их можно передать источнику данных. Обычно это делается путем вызова метода Update адаптера данных. Данный метод в цикле просматривает все записи таблицы и определяет, какие операции необходимо выполнить (обновление, добавление или удаление), и, если таковые вообще имеются, выполняет соответствующие команды. Если при просмотре очередной строки метода Update адаптера данных обнаруживает, что строка изменялась, то он автоматически вызовет надлежащую команду данных ( DataCommand ) и обновит на ее основе соответствующую строку в базе данных.

Структура SQL -запроса команды данных будет следующая:

  •  будет задействован SQL -запрос с предложением UPDATE. Адаптер данных знает, что предложение UPDATEприменяется для тех строк, свойства RowState которых имеет значение Modified ;
  •  в SQL -запрос будет включено предложение WHERE, указывающее, что обновляться будет строка, для которой, например EmployeeID = 4. Эта часть SQL -запроса отличает целевую строку от всех других строк, потому что поле EmployeeID является первичным ключом таблицы базы данных. Информация для предложенияWHERE будет получена не из текущей, а из оригинальной (первоначальной) версии записи (DataRowVersion.Original ), потому что в текущей версии записи пользователь мог изменить значение первичного ключа.
  •  в SQL -запрос будет включено предложение SET, для того, чтобы установить новые значения столбцов в соответствующей записи таблицы базы данных.

Обработка исключительных ситуаций при обновлении источника данных из набора данных. После того, как набор данных был изменен и эти изменения приняты, приложение должно вернуть новые данные назад источнику данных. Чтобы модернизировать источник данных содержанием набора данных вызывается метод Update адаптера данных. Адаптер данных выполнит соответствующую команду ( insertupdate или delete ), используя значение свойства RowState каждой строки набора данных.

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

  1.  Вызов метода Update адаптера данных должен выполняться внутри блока Try...Catch.
  2.  Если возникла исключительная ситуация, то нужно определить при обработке какой строки набора данных произошла ошибка.
  3.  Исправление возникшей проблемы в строке данных (либо программным способом, либо, представив пользователю ошибочную строку для внесения в нее изменений), и затем - повторная попытка модернизации источника данных.

Следующий пример показывает, как делать модернизацию источника данных внутри блока Try...catchсодержанием набора данных с именем.

try

{ daEmployee.Update(dsEmployee, "Employee"); }

catch (Exception e)

{

 // Код обработки ошибочной ситуации.

 String err = e.msg;

 MessageBox.Show("Ошибка обновления таблицы базы данных

Employee"  + err);

}

Обновление связанных таблиц. Если в наборе данных содержится несколько таблиц, то их необходимо модифицировать индивидуально, вызывая отдельно метод Update каждого адаптера данных. Если таблицы имеют реляционные отношения, то потребуется специфическое обновление базы данных. Обычно в этом случае изменяются и родительская запись и связанные с ней дочерние записи набора данных. Например, при добавлении новой должности формируется одна или более связанных записей сотрудников. Если в самой базе данных заданы правила обеспечения целостности, то при обновлении возможно возникновение ошибок. Например, если переслать в базу данных вновь появившиеся дочерние записи раньше, чем была переслана родительская запись. Поэтому необходимо выполнять определенную последовательность в пересылке: сначала должны послаться новые родительские записи, а потом дочерние.

Наоборот, если вы удаляете связанные записи в наборе данных, необходимо посылать обновления в базу данных в обратном порядке: сначала от дочерней таблицы, а потом - от родительской. В противном случае при обновлении информации в базе данных возникнет ошибка, потому что правила обеспечения целостности не позволят удалить родительскую запись, пока существуют связанные дочерние записи.

Последовательность обновления связанных таблиц. При обновлении связанных таблиц набора данных очень важно соблюдать определенную последовательность, чтобы не нарушить целостность данных основного источника и не сгенерировать ошибочную ситуацию. Чтобы предотвратить возможные ошибки нарушения целостности данных необходимо модернизировать источник данных в следующей последовательности:

  •  дочерняя таблица: удалить записи;
  •  родительская таблица: добавить, изменить или удалить записи;
  •  дочерняя таблица: добавить или изменить записи.

Для модернизации источника данных из набора данных, который содержит две или более связанных таблиц вызовите метод Update каждого адаптера данных.

Следующий пример показывает, как модернизировать источник данных из набора данных, который содержит связанные таблицы. Чтобы следовать за вышеупомянутой последовательностью, создаются три временных набора данных дочерней таблицы, которые содержат только добавленные, только удаленные и только измененные записи. Метод Update вызывается для каждого поднабора данных внутри блока Try...catch. Если при обновлении возникнут ошибки, то они будут перехвачены и обработаны также внутри этого блока (в обработчике исключительных ситуаций). После обновления источника данных вызывается метод AcceptChanges, который "принимает" сделанные изменения и, наконец, удаляются временные наборы данных, чтобы освободить ресурсы.

void UpdateAttemp( )

{

//Набор dsl содержит только удаленные записи дочерней таблицы

DataTable dsl = anyDataset.ChildTableName.GetChanges(DataRowState.Deleted);

//Набор ds2 содержит только добавленные записи дочерней таблицы

DataTable ds2 =

anyDataset.ChildTableName.GetChanges(DataRowState.Added);

//Набор ds3 содержит только измененные записи дочерней таблицы

DataTable ds3 =anyDataset.ChildTableName.GetChanges(DataRowState.Modified);

try

{

//Удаление записей дочерней таблицы

DataAdapter2.Update(dsl);

// Добавление и удаление записей родительской таблицы

DataAdapterl.Update(anyDataset, "ParentTable");

// Добавление записей в дочернюю таблицу

DataAdapter2.Update(ds2);

// Обновление записей дочерней таблицы

DataAdapter2.Update(ds3);

// Завершение процесса модернизации набора данных

anyDataset.AcceptChanges( );

// Удаление временных наборов данных

dsl.Dispose ( );

ds2.Dispose( );

ds3.Dispose( );

}

catch (Exception x)

{

// Обработчик ошибочных (исключительных) ситуаций.

}

}

Модификация данных

Модификация данных в приложении реализуется методом Edit. Для модификации данных необходимо для элементов контроля задать режим редактирования, вызвав метод DisplayEdit и запретить доступ к списку сотрудников в элементе listBoxEmployee. Активизация режима модификации данных по сотруднику осуществляется из пункта меню Действие/Изменить.

private void Edit ( )

{

DisplayForm (false);

this.listBoxEmployee.Enabled = false;

}

При проектировании приложения использовалась технология привязки источника ( DataSet ) данных к элементам управления ( TextBox, ListBox, ComboBox ). При выводе данных на экранную форму проведенная привязка обеспечивала корректность работы приложения. При модификации данных в элементах контроля для текстового поля TextBox механизм связывания автоматически поддерживает синхронизацию между элементом контроля и источником данных. Для списка ComboBox необходимо использовать событие SelectionChangeCommitted, которое им генерируется, когда пользователь изменяет выбранный элемент и подтверждает его изменение. Обработчик этого события принимает аргумент EventArgs. Этот обработчик целесообразно использовать для получения нового значения из ComboBox, когда пользователь его изменит. Для элементов управление обработчики событияSelectionChangeCommitted представлены ниже:

private void comboBoxJobRole_SelectionChangeCommitted(object sender, System.EventArgs e)

{

// Определяем позицию в таблице Employee

int pos = -1;

 pos = this.BindingContext[dsEmployee1,

"Employee"].Position;

// Изменение в таблице Employee поля JobRoleID при изменении

// выбора должности (comboBoxJobRole)

dsEmployee1.Employee[pos].JobRoleID =

(short)((DataRowView)comboBoxJobRole.Items[comboBoxJobRole.SelectedIndex])

["JobRoleID"];

}

private void comboBoxAccess_SelectionChangeCommitted(object sender, System.EventArgs e)

{

int pos = -1;

pos = this.BindingContext[dsEmployee1,

"Employee"].Position;

dsEmployee1.Employee[pos].Access =

comboBoxAccess.SelectedItem.ToString();

}

private void comboBoxStatus_SelectionChangeCommitted(object sender, System.EventArgs e)

{

int pos = -1;

pos = this.BindingContext[dsEmployee1,

"Employee"].Position;

dsEmployee1.Employee[pos].EmployeeStatus =

comboBoxStatus.SelectedIndex;

}

Далее можно изменять данные по сотруднику на форме. После изменения данных необходимо сохранить сделанные изменения.

Сохранение данных

Сохранение данных в приложении реализуется методом Save, который активизируется при выборе пункта менюДействие/Сохранить. Для сохранения модифицированной информации в приложении необходимо вначале завершить текущее обновление всех связанных с помощью объектов Binding элементов управления Windows Forms и источника данных. Для этого необходимо вызвать метод EndCurrentEdit класса BindingManagerBase:

bmEmployee.EndCurrentEdit( )

Далее формируется таблица ds1, в которую включаются только модифицированные строки:

DataSetEmployee.EmployeeDataTable ds1 = (DataSetEmployee.EmployeeDataTable)dsEmployee.Employee.

GetChanges(DataRowState.Modified);

Если таблица ds1 не пуста (условиеds1 != null ) осуществляется попытка обновления базы данных с помощью метода Update адаптера daEmployee и далее уничтожается таблица ds1. Если обновить базу данных не удается, то формируется сообщение об ошибке:

if(ds1 != null)

  try

  {

    this.daEmployee.Update(ds1);

    ds1.Dispose( );

    dsEmployee.Employee.AcceptChanges();

  }

  catch(Exception x)

  {

    string mes = x.Message;

   MessageBox.Show("Ошибка обновления базы данных Employee "+mes, "Предупреждение");

    this.dsEmployee.Employee.RejectChanges();

  }

При завершении алгоритма обновления форма FormEmployee переводится в режим "только для чтения" с помощью метода DisplayReadOnly и фокус должен быть на элементе управления textBoxSurname.

Полный текст модифицированного метода Save приведен далее:

private void Save()

{

   string mes = "";

// Завершение текущих обновлений всех  связанных с помощью

// объектов Binding элементов управления

   bmEmployee.EndCurrentEdit();

///Формирование таблицы, в которую включаются только

// модифицированные строки

   DataSetEmployee.EmployeeDataTable ds1 = (DataSetEmployee.EmployeeDataTable)dsEmployee.Employee.

GetChanges(DataRowState.Modified);

   if(ds1 != null)

       try

       {

           this.daEmployee.Update(ds1);

           ds1.Dispose( );

           dsEmployee.Employee.AcceptChanges();

       }

       catch(Exception x)

       {

           string mes = x.Message;

           MessageBox.Show("Ошибка обновления базы данных Employee "+mes, "Предупреждение");

           this.dsEmployee.Employee.RejectChanges();

       }

   DisplayForm(true);

   listBoxEmployee.Enabled = true;

   textBoxSurname.Focus();

}

Протестируйте добавленный в программу код.

Добавление данных

Создание новой записи с данными по сотруднику в приложении реализуется методом New. При добавлении новых записей в таблицу Employee базы данных необходимо:

  1.  Создать новую строку

DataRow rowEmployee = this.dsEmployee.Employee.NewEmployeeRow();

  1.  Сформировать начальные значения для элементов строки
  2.  rowEmployee["JobRoleID"] = 1;
  3.  rowEmployee["EmployeeStatus"] = 0;
  4.  rowEmployee["EmployeeSurname"] = "";
  5.  rowEmployee["EmployeeName"] = "";
  6.  rowEmployee["EmployeePatronymic"] = "";

rowEmployee["Access"] = "не задано";

  1.  Добавить сформированную строку к таблице Employee

dsEmployee.Employee.Rows.Add(rowEmployee);

  1.  Установить активную позицию в таблице Employee на добавленную строку
  2.  int pos = this.dsEmployee.Employee.Rows.Count - 1;

this.BindingContext[dsEmployee, EmployeeID].Position = pos;

  1.  Задать режим редактирования формы

DisplayForm(false);

  1.  Сделать список сотрудников недоступным для выбора

listBoxEmployee.Enabled = false;

  1.  Установить фокус на элементе textBoxSurname

textBoxSurname.Focus();

После задания данных по новому сотруднику необходимо их запомнить в базе данных. Для этого требуется модифицировать метод Save, добавив в него фрагмент кода для вставки новых записей перед кодом, модифицирующим записи.

/// Формирование таблицы, в которую включаются только добавленные строки

DataSetEmployee.EmployeeDataTable ds2 = (DataSetEmployee.EmployeeDataTable)dsEmployee.Employee.

GetChanges(DataRowState.Added);

if(ds2 != null)

  try

  {

   daEmployee.Update(ds2);

   ds2.Dispose();

    dsEmployee.Employee.AcceptChanges( );

  }

  catch(Exception x)

   {

    string mes = x.Message;

   MessageBox.Show("Ошибка вставки записи в базу данных Employee "+mes, "Предупреждение");

   this.dsEmployee.Employee.RejectChanges();

  }

В добавляемом фрагменте проверяется наличие в таблице Employee добавленных строк

ds2 != null

и если они имеются, то производится попытка модифицировать базу данных

daEmployee.Update(ds2);

При вставке новых записей в базу данных метод Update адаптера daEmployee вызывает SQL команду INSERT, которая была сформирована при генерации адаптера. Если первичный ключ таблицы базы данных является суррогатным и генерируется сервером автоматически (задано свойство IDENTITY ), которое корректируется в DataSet.

Протестируйте добавленный в программу код.

Удаление данных

Удаление записи с данными по сотруднику в приложении реализуется методом Remove. В процессе удаления записей по сотрудника используется модальное диалоговое окно для вывода сообщения (см. лабораторную работу 4), вид которого представлен на рисунке 10.2, для предупреждения пользователя при проведении операции.


Рис. 10.2.  Диалоговое окно предупреждения пользователя.

При выборе пункта меню Действие/Удалить формируется событие, которое обрабатывается методом toolStripButtonRemove_Click. Обработчик вызывает метод Remove, который выполняет удаление данных по сотруднику. В методе Remove определяется позиция, которую необходимо удалить в таблице Employee

int pos = -1;

pos = this.BindingContext[dsEmployee, "Employee"].Position;

Затем формируется строка с фамилией, именем и отчеством, удаляемого сотрудника

string mes = textBoxSurname.Text.ToString().Trim() + " "

 + textBoxName.Text.ToString().Trim() + " " +

 textBoxPatronymic.Text.ToString().Trim();

и выводится сообщение в диалоговом окне

MessageBox.Show(" Удалить данные  \n по сотруднику \n"+ mes+ "?", "Предупреждение",

 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);

Далее в зависимости от того, какую кнопку нажал пользователь, осуществляется удаление записи. Если пользователь нажал кнопку "Да", то необходимо выполнить следующий код:

this.dsEmployee.Employee.Rows[pos].Delete();

if (this.dsEmployee.Employee.GetChanges(DataRowState.Deleted) != null)

{

 try

 {

   this.daEmployee.Update(dsEmployee.Employee);

   this.dsEmployee.Employee.AcceptChanges();

 }

 catch (Exception x)

 {

   string er = x.Message.ToString();

   MessageBox.Show("Ошибка удаления записи в базе данных Employee " + er, "Предупреждение");

   this.dsEmployee.Employee.RejectChanges();

 }

}

При нажатии кнопки "Нет", то необходимо выполнить код:

this.dsEmployee.Employee.RejectChanges();

Протестируйте добавленный в программу код.

Отмена изменений

Отмена модификации записи с данными по сотруднику в приложении реализуется методом Undo. При отмене изменений необходимо завершить текущие обновления связанных элементов управления

bmEmployee.EndCurrentEdit();

и с помощью метода RejectChanges отменить изменения в источнике данных

dsEmployee.Employee.RejectChanges();

Далее необходимо задать режим "только для чтения", выбор строки в списке сотрудников listBoxEmployee и установить фокус на форме.

Задание на лабораторную работу

  1.  Изучите теоретический материал.
  2.  Разработайте методы для модификации, формирования, удаления и сохранения данных по сотрудникам.
  3.  Разработайте метод для отмены модификации данных по сотрудникам.
  4.  Протестируйте приложение.

11. Лабораторная работа: Упорядочивание списков и вычисляемые столбцы DataSet

Содержание

  •  Основные положения
  •  Упорядочение списка сотрудников по алфавиту
    •  Конфигурирование Data Adapter
  •  Формирование отображения списка сотрудников с полными данными
  •  Задание на лабораторную работу

Цель работы: Изучить основные приемы и способы сортировки данных при заполнении данными DataSet, динамическое изменение структуры DataSet, создание вычисляемых столбцов вDataSet и связывание их с элементами представления

Основные положения

В результате выполнения лабораторных работ 1 - 10 разработано приложение для учета сотрудников предприятия, основная экранная форма которого приведена на рисунке 11.1.

Рис. 11.1.  Экранная форма учета сотрудников предприятия

При аттестации разработанного приложения конечными пользователями были сделаны следующие замечания:

  •  список сотрудников необходимо упорядочить по алфавиту;
  •  в списке сотрудников необходимо указывать фамилию, имя и отчество.

Упорядочение списка сотрудников по алфавиту

Данные о сотрудниках считываются из таблицы Employee базы данных с помощью SQL -запроса в объект классаDataSet, с которым связан элемент визуализации данных listBoxEmployee. Данные из таблицы Employee базы данных заполняют таблицу DataSetEmployee в той последовательности, как они записаны в базе данных и соответственно в той же последовательности и отображаются в элементе визуализации данныхlistBoxEmployee. Для упорядочения списка сотрудников по алфавиту достаточно упорядочить данные получаемые из базы данных с помощью SQL -запроса, т.е. необходимо модифицировать команду Select.

Для формирования новой команды Select необходимо переконфигурировать Data Adapter - daEmployee.

Конфигурирование Data Adapter

  1.  В дизайнере класса DataSetEmployee выделите EmployeeTableAdapter (рисунок 11.2) и через контекстное меню откройте помощник конфигуратора адаптера Table Adapter Configuration Wizard (рисунок 11.3).

Рис. 11.2.  Дизайнер класса DataSetEmployee

Рис. 11.3.  Окно помощника конфигуратора адаптера

  1.  В окне Table Adapter Configuration Wizard нажмите кнопку Query Builder (рисунок 11.3) . В результате будет выведено окно Query Builder построителя SQL -запросов (рисунок 11.4).

Рис. 11.4.  Окно Query Builder построителя SQL-запросов

  1.  В окно Query Builder построителя SQL -запросов для колонки EmployeeSurname укажите тип сортировки (Sort Type ) - по алфавиту - Ascending (рисунок 11.5). После этого в команде Select добавится код

ORDER BY EmployeeSurname

Полный вид команды Select следующий:

SELECT JobRoleID, EmployeeSurname, EmployeePatronymic,

EmployeeID, EmployeeName, EmployeeStatus, Access, NetName, FirstDate

FROM Employee

ORDER BY EmployeeSurname

Рис. 11.5.  Задание режима сортировки данных по фамилии сотрудника

  1.  Завершите формирование SQL -запроса, нажимая кнопки "OK" и "Next" в окне Query Builder.

После компиляции и запуска приложения список сотрудников будет упорядочен по алфавиту, как показано на рисунке 11.6.

Рис. 11.6.  Экранная форма с упорядоченным списком сотрудников

Формирование отображения списка сотрудников с полными данными

Для формирования в списке сотрудников информации об фамилии, имени и отчестве необходимо в таблицуEmpoyee объекта dsEmployee класса