При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Привязка 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; } } } }