Поиск данных
Технология ADO .NET предоставляет значительные возможности для поиска данных - такие объекты, как DataSet, DataTable, содержат специализированные методы для быстрого решения этой задачи. Между тем свойство RowFilter объекта DataView может применяться для создания простого и эффективного поиска. Запускаем Visual Studio .NET и создаем новый проект. В окне New Project выбираем тип Windows Control Library, называем его "FindControl" (рис. 9.16):
Рис. 9.16. Выбор шаблона Windows Control Library
Появляется форма пользовательского (композитного) элемента управления. Устанавливаем следующие свойства:
Name | FindCheckBox |
Size | 230; 70 |
В окне Solution Explorer изменяем название "UserControl1.cs" на "FindCheckBox.cs". Перетаскиваем на форму из окна Toolbox текстовое поле, надпись и элемент CheckBox. Настраиваем их свойства:
Name | chbForSearching |
Location | 8; 32 |
Text | |
Name | txtColumnValue |
Location | 32; 32 |
Size | 184; 20 |
Text |
Name | lblColumnName |
Location | 40; 8 |
Text | ColumnName |
Переходим к коду. В конструкторе формы отключаем доступность текстового поля и привязываем обработчик события CheckedChanged для элемента CheckBox:
public FindCheckBox() { InitializeComponent(); txtColumnValue.Enabled = false; chbForSearching.CheckedChanged += new EventHandler(chbForSearching_CheckedChanged); }
В классе формы создаем обработчик события CheckedChanged для CheckBox и определяем действия для значений текстового поля, надписи и элемента CheckBox:
private void chbForSearching_CheckedChanged(object sender, EventArgs e) { txtColumnValue.Enabled = chbForSearching.Checked; } [Category("Appearance"), Description("Название поля, по которому будет осуществляться поиск")] public string ColumnName { get {return lblColumnName.Text;} set {lblColumnName.Text = value;} } [Category("Appearance"), Description("Ключевое слово для поиска")] public string ColumnValue { get {return txtColumnValue.Text;} set {txtColumnValue.Text = value;} }
[Category("Appearance"), Description("Включение поиска по заданному полю")] public bool SearchEnabled { get {return chbForSearching.Checked;} set {chbForSearching.Checked = value;} }
Свойства ColumnName, ColumnValue и SearchEnabled будут свойствами композитного элемента управления, которые будут отображаться в его окне Properties. В квадратных скобках указан атрибут для помещения свойства в заданную группу и описание, выводимое на информационную панель. Компилируем приложение (Ctrl+Shift+B) и закрываем его. Создаем новое Windows-приложение, называем его "FindCustomers". Перетаскиваем на форму следующие элементы управления: Panel (свойству Dock устанавливаем значение Left), Splitter и DataGrid (свойству Dock устанавливаем значение Fill). В окне Toolbox щелкаем правой кнопкой мыши на вкладке Windows Forms и в появившемся контекстном меню выбираем пункт "Add \ Remove Items_". В появившемся окне Customize Toolbox на вкладке .NET Framework Components нажимаем кнопку "Browse" (рис. 9.17, А) и переходим в директор ию, где расположена сборка композитного элемента FindControl (у меня это D:\Uchebnik\Code\Glava4\FindControl\bin\Debug, сборка FindControl.dll) (рис. 9.17, Б). После выбора сборки она появляется в окне Customize Toolbox (рис. 9.17, В).
увеличить изображение
Рис. 9.17. Добавление композитного элемента. А - окно "Customize Toolbox", Б - Выбор сборки FindControl.dll, В - добавленная сборка на вкладке ".NET Framework Components"
Нажимаем кнопку "OK" и перетаскиваем на панель формы из окна Toolbox четыре копии элемента FindCheckBox. Добавляем также кнопку поиска (рис. 9.18). Устанавливаем следующие свойства элементов:
ColumnName | CustomerID |
Name | fcbCustomerID |
ColumnName | CompanyName |
Name | fcbCompanyName |
ColumnName | ContactName |
Name | FcbContactName |
ColumnName | Phone |
Name | fcbPhone |
Name | btnSearch |
Text | Поиск |
увеличить изображение
Рис. 9.18. Расположение элементов на форме. Окно Properties композитного элемента
Обратите внимание (рис. 9.18), что в окне Properties, при групповом расположении, свойство ColumnName находится в группе Appearance. На информационную панель выводится описание этого свойства на русском языке. Именно эти параметры мы и указывали при создании композитного элемента.
Для того чтобы упростить код, создадим подключение к базе данных при помощи визуальных средств студии. В окне Toolbox переходим на вкладку Data, перетаскиваем на форму SqlDataAdapter и настраиваем извлечение таблицы Customers базы данных NorthwindCS. Выделяем затем sqlDataAdapter1 на панели компонент, в окне Properties переходим по ссылке "Generate DataSet". Вводим имя "dsCustomers". В конструкторе формы добавляем код для заполнения элемента DataGrid данными при загрузке:
public Form1() { InitializeComponent(); sqlDataAdapter1.Fill(dsCustomers1); dataGrid1.DataSource = dsCustomers1.Tables["Customers"].DefaultView; }
В классе формы создаем метод FindCustomers, в котором будет осуществляться обработка1):
private void FindCustomers() { //Создаем экземпляр filteringFields класса ArrayList ArrayList filteringFields = new ArrayList(); //Если элемент fcbCustomerID доступен для поиска if (fcbCustomerID.SearchEnabled) //Добавляем в массив filteringFields значение текстового поля ColumnValue filteringFields.Add("CustomerID LIKE \'" + fcbCustomerID.ColumnValue + "%\'");
if (fcbCompanyName.SearchEnabled) filteringFields.Add("CompanyName LIKE \'" + fcbCompanyName.ColumnValue + "%\'");
if (fcbContactName.SearchEnabled) filteringFields.Add("ContactName LIKE \'" + fcbContactName.ColumnValue + "%\'");
if (fcbPhone.SearchEnabled) filteringFields.Add("Phone LIKE \'" + fcbPhone.ColumnValue + "%\'");
string filter = ""; //Комбинируем введенные в текстовые поля значения. //Для объединения используем логический оператор "ИЛИ" if (filteringFields.Count == 1) filter = filteringFields[0].ToString(); else if (filteringFields.Count > 1) { for(int i = 0; i < filteringFields.Count - 1; i++) filter += filteringFields[i].ToString() + " OR "; //Для объединения полей в запросе используем логический оператор "И" //for(int i = 0; i < filteringFields.Count - 1; i++) //filter += filteringFields[i].ToString() + " AND ";
filter += filteringFields[filteringFields.Count - 1].ToString(); } // Создаем экземпляр dvSearch класса DataView DataView dvSearch = new DataView(dsCustomers1.Customers); //Передаем свойству RowFilter объекта DataView скомбинированное значение filter dvSearch.RowFilter = filter; dataGrid1.DataSource = dvSearch; }
Добавляем обработчик кнопки "Поиск":
private void btnSearch_Click(object sender, System.EventArgs e) { try { FindCustomers(); } catch(Exception ex) { MessageBox.Show(ex.Message); } }
Запускаем приложение. При определении логического оператора "ИЛИ" в методе FindCustomers поисковый запрос выводит записи, содержащие хотя бы одно значение из введенных полей (рис. 9.19, А), при определении оператора "И" - запись, содержащую все эти значения (рис. 9.19, Б).
увеличить изображение
Рис. 9.19. Готовое приложение "FindCustomers". А - Запрос с оператором "ИЛИ" возвращает две записи, содержащие в разных полях введенное значение. Б - Запрос с оператором "И" не возвращает ничего, поскольку в таблице нет ни одной записи, содержащей оба значения
В программном обеспечении к курсу вы найдете приложения FindControl и FindCustomers (Code\Glava4\ FindControl и FindCustomers).