Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Лекция 2:

Привязка WPF к таблице данных ADO.NET

< Лекция 1 || Лекция 2: 123456 || Лекция 3 >
Аннотация: Подробно описаны все аспекты привязки WPF к таблице данных ADO.NET.

Упражнение 1. Привязка интерфейсных элементов к таблице ADO.NET базы данных OLE DB

Сейчас редкое приложение обходится без данных, хранящихся в центральном большом хранилище (Store - хранилище), - базе данных (БД). Такие приложения обычно называют управляемые данными. Их можно построить и по технологии WPF. Для взаимодействия с БД традиционно используются возможности объектов ADO.NET, а вот для отображения данных можно применить элементы и механизмы WPF, в том числе - привязку.

Главная трудность, которая нас ожидает при выполнении упражнений данной темы, - вспомнить классы ADO.NET и правильно их использовать. Такая ситуация естественна, пока не накопилось нужного количества практического опыта, а это дело наживное. Тем более, что необходимый для понимания данной темы минимум сведений по ADO.NET был изложен в начале этого курса, и к нему всегда, при необходимости, можно вернуться.

Начнем с привязки списковых элементов WPF к табличным объектам ADO.NET для простого просмотра. Нам нужно будет извлечь данные из БД и заполнить ими некоторый объект, способный автономно хранить добытые данные в оперативной памяти, не занимая при этом соединение с базой данных. Затем следует связать какой-нибудь списковый интерфейсный элемент WPF с этим объектом - источником данных.

В качестве хранилища данных будем использовать учебную базу данных Northwind.mdb типа OLE DB (Object Linking and Embedding Database). К такому типу БД относятся и базы файлового типа Microsoft Access с расширением .mdb (Microsoft Database). Наш выбор основан на том, что для таких баз не требуется устанавливать дополнительные программы, типа SQL Server.

Более того, в данном упражнении пока будем работать только с таблицей Employees БД Northwind.mdb (для единообразия). Постепенно перейдем и к другим таблицам, особенно при рассмотрении вопросов работы со взаимосвязанными таблицами БД, находящимися в отношении (Relations) "главная-подробности" (" master-detail ").

Для удобства, еще раз приведем схему, отображающую структуру БД Northwind.mdb, с которой мы ранее уже встречались


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

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

  • Хранилище данных (Data Store) - место, где хранятся сами структурированные данные. В нашем случае это MDF-файл
  • Доступ к данным (Data Access Layer) - код, который необходим для извлечения и манипулирования необработанными данными. В нашем случае это классы ADO.NET и возможные пользовательские (программистские) надстройки над ними
  • Бизнес-логика (Business Logic Layer) - код, который обрабатывает данные в соответствии с поставленной задачей для последующего представления их пользователю. Здесь учитывается специфика обрабатываемых данных и обеспечивается их целостность и непротиворечивость. Обычно, это основная часть ручной работы, которая полностью ложится на плечи программиста
  • Представление данных/Пользовательский интерфейс (Presentation/Eser Interface Layer - UI) - код, который определяет, что именно пользователь должен видеть на экране. Сюда относятся визуальные элементы форматирования, сортировки и фильтрации данных, навигационные меню, списки, кнопки и другие интерактивные элементы управления

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

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

Подготовка проекта для выполнения упражнения

  • Командой File/New/Project создайте новое решение DataBindingTable с одноименным проектом

  • В панели Solution Explorer выделите корень проекта и командой Add/New Folder контекстного меню создайте подкаталог Data
  • Через контекстное меню панели Solution Explorer скопируйте из прилагаемой папки Source файл Northwind.mdb командой Add/Existing Item (измените фильтр диалогового окна на All Files). При появлении мастера Data Source Configuration Wizard отмените его кнопкой Cancel, поскольку мы пока не собираемся создавать типизированный набор данных
  • Выделите в панели Solution Explorer файл Northwind.mdb и через панель Properties проверьте, что его свойства имеют значение
  • Build Action=Content
  • Copy to Output Directory=Copy always
  • В панели Solution Explorer добавьте для корневого узла проекта командой Add/New Item заготовку файла конфигурации приложения с именем App.config

  • Заполните конфигурационный файл App.config кодом настройки строки соединения с БД, значение которой мы будем извлекать в процедурном коде во время выполнения приложения с помощью класса ConfigurationManager
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="MyNorthwind"
        connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
            Data Source=|DataDirectory|\Data\Northwind.mdb"
        providerName="System.Data.OleDb" />
  </connectionStrings>
</configuration>
  • В панели Solution Explorer вызовите для узла References проекта контекстное меню и командой Add Reference добавьте ссылку на библиотечную сборку System.Configuration.dll, в которой находится нужный нам класс ConfigurationManager для работы с конфигурационным файлом App.config из процедурного кода

  • Выделите в панели Solution Explorer узел проекта и добавьте к нему командой Project/Add Class новый файл с именем StoreNorthwindDB.cs

  • Добавьте в начало файла StoreNorthwindDB.cs строку подключения пространств имен инфраструктуры ADO.NET и заполните класс StoreNorthwindDB следующим кодом
using System;
using System.Collections.Generic;
using System.Text;
    
// Подключение пространств имен инфраструктуры ADO.NET
using System.Data;
using System.Data.OleDb;
using System.Windows;// Для MessageBox
    
namespace DataBindingTable
{
    // Класс для доступа к БД
    public class StoreNorthwindDB
    {
        // Извлекаем в поле строку соединения из файла App.config
        String connectionString = System.Configuration.
            ConfigurationManager.ConnectionStrings["MyNorthwind"].ConnectionString;
    
        //*********************************************************
        // Метод извлечения данных из таблицы Employees
        // хранилища базы данных в ADO.NET-объект DataTable
        //*********************************************************
        DataTable dtEmployees = null;// Ссылка на объект DataTable
        public DataTable LoadTableEmployees()
        {
            // Загрузим таблицу Employees только один раз
            if (dtEmployees != null)
                return dtEmployees;
    
            // Заполняем объект таблицы Employees данными из БД
            dtEmployees = new DataTable();
            using (OleDbConnection conn = new OleDbConnection(connectionString))
            {
                OleDbCommand selectCommand = conn.CreateCommand();
                OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
    
                // Загружает данные и схему таблицы Employees
                selectCommand.CommandText = "SELECT EmployeeID, " +
                    "(LastName + ', ' + FirstName) AS FullName, " +
                    "Address, BirthDate, Region FROM Employees";
    
                try
                {
                    // Метод сам открывает БД и сам же ее закрывает
                    adapter.Fill(dtEmployees);
                }
                catch
                {
                    MessageBox.Show("Ошибка подключения к БД");
                }
                finally
                {
                    conn.Close(); // На всякий случай!
                }
            }
    
            return dtEmployees;
        }
    }
}

Инструкция using(), в которой создается соединение с БД, автоматически закроет его после выполнения своего блока кода, хотя то же самое сделает и метод adapter.Fill(). В SQL-запросе к БД наряду с извлечением столбцов оригинальных мы одновременно формируем вычислимый столбец FullName. Метод LoadTableEmployees(), который будет вызываться в клиенте класса, вернет ссылку на объект dtEmployees типа DataTable, загруженный данными таблицы.

Для того, чтобы получить только один экземпляр класса StoreNorthwindDB, и чтобы он был доступен во всех окнах приложения, разместим код его создания в классе App.

  • Откройте файл App.xaml.cs и добавьте в класс App уровня приложения следующий код
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Windows;
    
namespace DataBindingTable
{
    public partial class App : Application
    {
        // Базовое поле для свойства
        private static StoreNorthwindDB storeNorthwindDB =
            new StoreNorthwindDB();
        // Свойство для базового поля со ссылкой на экземпляр класса
        public static StoreNorthwindDB StoreNorthwindDB
        {
            get { return storeNorthwindDB; }
        }
    }
}
< Лекция 1 || Лекция 2: 123456 || Лекция 3 >
Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?

Dmitriy Ivanchenko
Dmitriy Ivanchenko
Украина, Кировоград, Виктория-П, 2011
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974