
- •В ведение в ado.Net
- •Потребитель данных
- •Поставщики данных
- •Источник данных — xml-файл
- •Элементы управления на форме Меню
- •Как устроены планки меню, статуса и панелей инструментов
- •Планка инструментов (ToolStrip)
- •Навигатор связей
- •Контейнер, расщепляющий форму
- •Создание таблиц и внедрение их в DataSet
- •Пояснения
- •Запись и чтение данных
- •Отображение данных связанной таблицы
- •Добавляем ограничение
- •Вторая, подчиненная таблица
- •Автоматическая навигация по записям связанной таблицы
- •Элемент управления BindingNavigator
- •Реакции на события в DataTable
- •Канонизация имен студентов
- •Вычисляемые колонки DataTable (Expression-Based DataColumn Objects)
- •Поиск в таблице DataTable и в компоненте DataGridView
- •Коррекция пользовательского интерфейса
- •Результат поиска
- •Поиск в DataGridView
- •Отбор данных из DataTable и отображение их в ListView
- •Как легко вносятся ошибки
- •Образ таблицы DataView
- •Методы Find и FindRows класса DataView
- •Задание
- •Элемент управления, который позволяет управлять отображением колонок DataGridView
Планка инструментов (ToolStrip)
Вместо элемента Toolbar, который работал в .NET Framework 1.1, используем элемент типа ToolStrip. Добавьте такой элемент с идентификатором toolStrip.
В свою внутреннюю коллекцию Items типа ToolStripItemCollection ToolStrip позволяет добавлять кнопки и некоторые другие элементы управления. Вы уже догадались, что кнопка с подсказкой Add ToolStripButton, автоматически появляющаяся на поверхности панели в режиме дизайна, служит для создания и добавления в коллекцию новых элементов. Используйте ее для вставки кнопок, меток, выпадающего списка и полей ввода. Вы можете, как и в случае с меню, воспользоваться Smart button ( ) и добавить набор стандартных кнопок, а затем удалить ненужные и добавить недостающие элементы. Все элементы управления должны быть идентифицироваы в поле (Name) окна свойств выделенного элемента.
Присвойте кнопкам (см. рис. выше) имена: btnOpen, btnSave, btnFindNext, btnFindList, btnFindView и btnAverage.
Добавьте в ToolStrip текстовые метки (элементы типа ToolStripLabel см. рис. выше). Установите для них значения свойств Name (lblFind, lblAvgLo, lblAvgHi), и Text (Find:, Average low:, hi:).
Добавьте выпадающий список (ToolStripComboBox) с именем comboFind. Он будет помнить искомые строки текста.
Добавьте два элемента типа ToolStripTextBox с именами: txtAvLo и txtAvgHi. Они будет использоваться для задания верхней и нижней границ поиска студентов по среднему баллу.
Навигатор связей
Навигатор связей (элемент типа BindingNavigator) нам не нужен, поэтому советую пропустить этот параграф. Но если вы хотите знать, как работать с такими элементами управления, то добавьте его на форму. Замените длинное имя навигатора на bn. Так как по умолчанию навигатор улегся на ToolStrip и закрыл ее, то измените значение его свойства Dock на константу перечисления DockStyle.Bottom (см. нижнюю часть формы), или манипулируйте настройками элементов формы так, чтобы и ToolStrip и BindingNavigator были видимы (не закрывали друг друга). Вы можете также переместить все элементы управления из ToolStrip в BindingNavigator и удалить ToolStrip, так как BindingNavigator способен его полностью заменить.
Контейнер, расщепляющий форму
Элемент управления типа SplitContainer очень удобен, поэтому мы обязательно его используем.
Положите на форму SplitContainer. Установите его свойства: Name=split, Dock=Fill, Orientation=Vertical.
В правую панель контейнера split вложите еще один SplitContainer и установите для него такие свойства: Name= splitRight, Orientation=Horizontal, Dock=Fill.
В верхнюю панель контейнера splitRight положите элемент типа DataGridView с именем Name=gridStud.
В нижнюю панель splitRight положите DataGridView с именем Name=gridExam.
В левую панель контейнера split положите элемент типа GroupBox с именем Name=grFind и текстом Search in :.
Внутрь контейнера GroupBox (см. рис.) вложите две метки (Label) со следующими свойствами: Name=lblTable, Text=Table: и Name=lblColumn, Text=Column:.
Туда же добавьте два списка типа ListBox (Name=listTable и Name=listColumn). В коллекцию Items первого списка добавьте две строки текста Studs и Exams, которые соответствуют именам таблиц.
Напомню, что любые сообщения удобно выводить с помощью отдельной формы FormMsg, которая исчезает по истечении заданного нами кванта времени. Форма FormMsg позволяет заменить вызовы MessageBox.Show(. . .) на строки вида:
new FormMsg("Please, wait. . .", 3000); // Эта форма будет жить 3 секунды
Добавьте в текущий проект класс по имени FormMsg. Код класса вы найдете в документе C# Практика (3-й семестр). Заметьте, что этот код расположен в единственном файле .cs (отсутствует файл дизайнера .designer.cs, и файл ресурсов .resx). Если вы случайно создали эти файлы (добавив в проект форму, а не класс), то удалите их и оставьте только один файл FormMsg.cs.
Вы можете также добавить на форму элемент типа StatusStrip, если найдете для него место. В коллекцию его дочерних элементов обычно добавляют элементы типа ToolStripStatusLabel. В планку статуса (точнее, в ее поля ToolStripStatusLabel) принято выводить сообщения. При нажатии кнопки поиска мы собираемся искать заданный текст в колонках DataTable. Результат поиска (или сообщение Not Found) можно вывести в строку статуса. Выберите способ отображения сообщений самостоятельно (FormMsg, панель статуса, или MessgeBox). Последний выбор буду рассматривать, как признак лени.
Всплывающая подсказка ToolTip автоматически устанавливается равной свойству Text кнопки на ToolStrip. Предлагаю установить это свойство для всех кнопок: Open, Save, Find List, Find View и Average. По умолчанию свойство Text копируется в свойство ToolTipText.
Измените значения свойства Image (изображение на кнопке). Для этого запустите диалог поиска изображения, нажав кнопку в правой части окна свойств, и выберите команду Import. Импортируйте картинку из вашей любимой папки с картинками (такую пора завести) или из архива со стандартными изображениями, который имеется в студии:
C:\Program Files\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\..
Реакции на нажатие новых кнопок (делегаты с заданиями) вы можете создать двумя разными способами.
Методом двойного щелчка по кнопкам toolStrip вы создаете стандартные методы (типа button_Clicked),
Выбрав в окне Properties для элемента toolStrip событие ItemClicked (включите вкладку событий Events).
Второй способ лучше, так как создается один метод, реагирующий на нажатия всех кнопок. Второй параметр этого метода (задания делегата) несет информацию о нажатой кнопке (или другой сущности из коллекции ToolStripItemCollection).
Код обработчика события ItemClicked имеет стандартную структуру, она также используется при работе с элементами типа Toolbar и BindingNavigator.
switch (e.ClickedItem.Text)
{
case "Open": Open(FileDlg(true)); break;
case "Save": Save(FileDlg(false)); break;
case "Find Next": Find(); break;
case "Find List": ShowList(GetSearchCriteria()); break;
case "Find View": ShowGrid(GetSearchCriteria()); break;
case "Average": ShowAverage(); break;
}
Вызываемые методы предстоит создать. Механизм Intellisense рвется в бой и предлагает создать временные заглушки для отсутствующих методов. Позвольте ему это сделать, но всегда проверяйте типы и идентификаторы данных параметров, которые он создаст. Он любит тип object, но нам часто нужен другой тип, например, string. Корректируйте заготовку так, чтобы не нарушался смысл происходящего. В дополнение к данным, которые были сгенерированы дизайнером студии, вручную введите в класс формы объявления нескольких переменных. Прежде всего добавьте в класс объявление объекта ds класса DataSet. Мы собираемся запомнить имя открытого файла с данными в переменной fileName, а также местоположение этого файла в переменной dirName. Далее нам понадобятся и другие переменные.
Добавьте объявления переменных в класс формы, как показано ниже. Инициализируйте их в конструкторе.
#region Data
DataSet ds;
BindingSource[] bs;
DataGridView[] grids;
DataView view;
int searchTableID, searchColumnID, searchRowID;
string dirName, fileName, searchFileName, findWhat;
Form formFound;
Random rand;
bool bFindNext;
static string[] courses = { "Math", "Mechanics", "Physics", "English", "Oracle", "OpenGL", "History" };
#endregion
public FormMain()
{
InitializeComponent();
rand = new Random(DateTime.Now.Millisecond);
dirName = FindFolder("Data");
if (dirName == null)
{
new FormMsg("Could not find Data folder", 4000);
return;
}
fileName = "Students.xml";
searchFileName = "MySearches.txt";
searchRowID = searchTableID = searchColumnID = 0;
grids = new DataGridView[] { gridStud, gridExam };
}
В папке проекта создайте папку Data (в ней будет храниться файл Students.xml). Данные следует хранить в специальной папке приложения, которая должна располагаться внутри папки вашего приложения. Эту задачу можно решить с помощью метода FindFolder, который предлагаю использовать во всех проектах, так как большиство проблем при переносе приложения на другой компьютер и задержек в его работе обусловлены поиском файлов с данными. Ни в коем случае данные не следует размещать в папке bin\Debug. Поиск данных в файловой системе при демонстрации результатов вашей работы — это могучий тормоз, который сильно портит настроение (во всяком случае мое).
string FindFolder (string name)
{
string dir = AppDomain.CurrentDomain.BaseDirectory; // Application.StartupPath;
for (char slash = '\\'; dir != null; dir = Path.GetDirectoryName (dir))
{
string res = dir.TrimEnd (slash) + slash + name;
if (Directory.Exists (res))
return res + slash;
}
return null;
}
Выбор AppDomain.CurrentDomain.BaseDirectory немного лучше, чем Application.StartupPath, так как он работает в консольных и в Web-приложениях, а последний работает только в приложениях типа Windows Forms.
Добавьте в конструктор формы обработчик события первоначальной загрузки формы (вручную Load += (s, e) => DoLoad();) и в ней определите позицию формы на рабочем столе. Это делает метод SetDesktopLocation класса Form. Просмотрите справку и убедитесь, что его надо вызывать после того, как форма показалась на экране. Многие действия с элементами формы следует производить после того, как отработал конструктор, то есть внутри обработчика события Load.
SetDesktopLocation(20, 20); // Позиция формы на рабочем столе
InitDataSet(); // Создайте заглушку этого метода с помощью Intellisense
InitTables(); // Заполнение таблиц DataTable (создайте заглушку)
RelateAndBind(); // Связывание таблиц DataTable (создайте заглушку)