При выполнении в лабораторной работе упражнения №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
Добавление вычислимого столбца
Сейчас вычислимый столбец тоже можно добавить в нужную коллекцию объектной модели набора, но поскольку данные уже заполнены, придется заново перебрать все строки коллекции и присвоить придуманному столбцу требуемыми значениями. А можно поступить по другому: добавить в коллекцию набора ДО ЕГО ЗАПОЛНЕНИЯ новый столбец, настроить его схему требуемым образом, а потом загрузить коллекцию данными из хранилища. Вычислимый столбец сразу будет пересчитан налету и заполнен данными. При этом выражение SQL-запроса менять не придется. Проверим оба способа.
- Верните свойство отображаемого столбца списка в прежнее значение DisplayMemberPath="FullName", где опять будет фигурировать имя несуществующего столбца коллекции Employees
- Дополните метод ReadDataSet() следующими двумя закомментированными блоками кода, каждый из которых готов создать вычислимый столбец FullName
//********************************************************* // Метод извлечения нетипизированного набора // данных из хранилища данных Northwind.mdb //********************************************************* DataSet ds = null;// Ссылка на нетипизированный набор DataSet public DataSet ReadDataSet() { // Загрузим набор данных только один раз if (ds != null) return ds; ds = new DataSet();// Создаем множественный набор данных // Заполняем множественный набор данных из БД using (OleDbConnection conn = new OleDbConnection(connectionString)) { OleDbCommand selectCommand = conn.CreateCommand(); OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand); /*////////////////////////////////////// // Добавления вычислимого столбца в еще // незаполненную коллекцию объектной модели //////////////////////////////////////// // Готовим вычислимый столбец FullName // для объекта-коллекции Employees // ДО ЕЕ ЗАПОЛНЕНИЯ В НАБОРЕ ДАННЫХ !!!!! ds.Tables.Add(new DataTable("Table"));// Дежурное имя по умолчанию DataColumn column = new DataColumn("FirstName"); column.DataType = typeof(string); ds.Tables[0].Columns.Add(column); // column = new DataColumn(); column.ColumnName = "LastName"; column.DataType = System.Type.GetType("System.String"); ds.Tables[0].Columns.Add(column); // column = new DataColumn("FullName", typeof(String)); column.Expression = "LastName + ', ' + FirstName"; ds.Tables[0].Columns.Add(column); //*///////////////////////////////////// // Загружаем всю таблицу Employees selectCommand.CommandText = "SELECT * FROM Employees"; adapter.Fill(ds);// Сам открывает, загружает и закрывает // Назначаем загруженным данным в наборе такое же имя, // как и в хранилище, чтобы в дальнейшем не путаться ds.Tables[0].TableName = "Employees"; // Загружает всю таблицу Customers selectCommand.CommandText = "SELECT * FROM Customers"; // Назначаем загружаемым данным в наборе имя, в этом способе // надо переопределить дежурное имя Table до заполнения набора adapter.TableMappings.Add("Table", "Customers");// Должен стоять перед adapter.Fill(ds); // Должен стоять после // Загружает всю таблицу Orders selectCommand.CommandText = "SELECT * FROM Orders"; // Загружаем и сразу этой порции данных назначаем имя в наборе adapter.Fill(ds, "Orders"); /*////////////////////////////////////// // Добавления вычислимого столбца в уже // заполненную коллекцию объектной модели //////////////////////////////////////// // Дублируем ссылку для удобства адресации DataTable tableEmployees = ds.Tables["Employees"]; DataColumn column = new DataColumn("FullName"); column.DataType = typeof(string); tableEmployees.Columns.Add(column); // Приведем к верхнему регистру для различения foreach (DataRow row in tableEmployees.Rows) row[column] = row["LastName"].ToString().ToUpper() + ", " + row["FirstName"].ToString().ToUpper(); //*///////////////////////////////////// return ds; } }
- Раскомментируйте поочередно один из блоков (но не оба сразу!) создания вычислимого столбца и испытайте работу приложения. Быстрый способ раскомментировать любой из приведенных блоков - добавить слэш перед открывающей скобкой многострочного комментария (перед звездочкой)
При реализации любого из рассмотренных способов вкладка Page4 будет выглядеть так, как и ожидалось
Вкладка Page5. Прямая привязка элементов интерфейса к таблице Employees в DataSet
В предыдущем примере мы привязывали набор данных к именованному списку, а затем выделенный элемент SelectedItem списка назначали в свойстве DataContext сетки Grid. К этому SelectedItem привязывались текстовые поля TextBox. Объект SelectedItem менялся при выборе пользователя, а следом менялись и значения TextBox. В этом примере набор данных мы присвоим свойству DataContext именованного элемента Grid, чтобы его там нашел и список, и текстовые поля.
- Добавьте к интерфейсной коллекции TabControl копию вкладки Page4 и преобразуйте ее во вкладку Page5 так
<!-- Прямая привязка элементов к набору данных DataSet --> <TabItem Header="Page5"> <Grid Name="grid5" > <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,3" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding Path=Employees}" DisplayMemberPath="FullName" IsSynchronizedWithCurrentItem="True" /> <TextBlock Grid.Row="1" Margin="0,0,5,0">EmployeeID:</TextBlock> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Employees/EmployeeID, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="2">FullName:</TextBlock> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Employees/FullName, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="3">Address:</TextBlock> <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=Employees/Address, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="4">BirthDate:</TextBlock> <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Path=Employees/BirthDate, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="5">Region:</TextBlock> <TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Path=Employees/Region, Mode=OneWay}" Focusable="False" /> </Grid> </TabItem>
Мы назначили элементу Grid имя для возможности присвоения в процедурном коде его свойству DataContext ссылки на набор данных. Это будет единственный именованный элемент в разметке вкладки Page5, потому что другие элементы мы программировать в процедурном коде не будем. В списке ListBox мы оставили неизменными свойство Path=Employees, означающее таблицу набора в элементе Grid.DataContext, к которой привяжется список, и - отображаемый вычислимый столбец FullName.
Имя списка мы убрали, но добавили атрибут IsSynchronizedWithCurrentItem="True", который заставляет синхронизировать перемещение курсора в коллекции Employees набора данных со сменой выделенного пользователем элемента списка. Привязываемое к набору свойство Text элементов TextBox должно конкретизировать коллекцию в наборе Grid.DataContext вместе с адресуемым свойством привязки.
- Добавьте в класс Window1 файла Window1.xaml процедурный код для инициализации источника привязки в именованной сетке Grid следующим образом
private void Window_Loaded(object sender, RoutedEventArgs e) { Page1(); Page2(); Page3(); Page4(); Page5(); } .................................................... #region Вкладка Page5 private void Page5() { // Назначаем источником набор данных DataSet в сетке grid5.DataContext = App.StoreNorthwindDB.ReadDataSet(); } #endregion
- Запустите приложение - вкладка Page5 работает
- Попробуйте убрать из списка атрибут IsSynchronizedWithCurrentItem="True" или заменить его значение на False - текстовые поля перестают отслеживать выделенные позиции списка: список и коллекция прекратили синхронную работу