При выполнении в лабораторной работе упражнения №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
Некоторые дополнительные модификации привязки во вкладке Page2
С последним примером можно немного поэкспериментировать, перенеся привязку списка ListBox из кода в разметку.
- Добавьте к разметке элемента ListBox вкладки Page2 в файле Window1.xaml следующую строку привязки
<ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,3" ScrollViewer.VerticalScrollBarVisibility="Auto" Name="listEmployees2" SelectionChanged="listEmployees2_SelectionChanged" ItemsSource="{Binding}" DisplayMemberPath="FullName" />
- Модифицируйте в классе Window1 файла Window1.xaml.cs функцию Page2() следующим образом
private void Page2() { // Загружаем данные и назначаем источник привязки employees2 = App.StoreNorthwindDB.ReadTableEmployees(); listEmployees2.SelectedIndex = 0; listEmployees2.Focus(); gridEmployees2.DataContext = employees2[0]; //listEmployees2.ItemsSource = employees2; //listEmployees2.DisplayMemberPath = "FullName"; listEmployees2.DataContext = employees2; }
В представлении XAML элемента списка свойство ItemsSource мы задали для объекта Binding без указания атрибутов. Поскольку свойство Source объекта Binding не задано, WPF начнет искать источник в свойстве DataContext текущего элемента, а при неудаче - далее будет искать его в родительских элементах вверх по визуальному дереву в направлении его корня. В процедурном коде мы присваиваем свойству DataContext значение объекта-коллекции employees2, тем самым указываем источник связывания в самом элементе списка listEmployees2. Свойство DisplayMemberPath="FullName" списка определяет столбец коллекции-источника, который будет отображаться на экране. В нашем случае - это вычислимый столбец таблицы ADO.NET.
- Запустите приложение и испытайте работу вкладки Page2 - ее функциональность осталась прежней
Можно пойти еще дальше в привязке на стороне разметки. Учитывая, что привязанные к элементу ListBox данные синхронно позиционирует свой внутренний курсор построчно в соответсвии с выделенным элементом SelectedItem списка, к этому элементу мы и привяжем свойство Grid.DataContext как к общему источнику данных для текстовых полей TextBox. Получится, что список (элемент управления элементами) привязан к коллекции, а элементы управления содержимым привязаны не к элементам коллекции, а к элементам списка.
- Выполните в открывающем дескрипторе элемента Grid вкладки Page2 следующие изменения
Было |
<Grid Name="gridEmployees2" > |
---|---|
Стало |
<Grid DataContext="{Binding ElementName=listEmployees2, Path=SelectedItem}" > |
- Удалите, за ненадобностью, из дескриптора элемента ListBox подписку обработчика на событие SelectionChanged
Было |
<ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,3" ScrollViewer.VerticalScrollBarVisibility="Auto" Name="listEmployees2" SelectionChanged="listEmployees2_SelectionChanged" ItemsSource="{Binding}" DisplayMemberPath="FullName" /> |
---|---|
Стало |
<ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,3" ScrollViewer.VerticalScrollBarVisibility="Auto" Name="listEmployees2" ItemsSource="{Binding}" DisplayMemberPath="FullName" /> |
- Удалите полностью, за ненадобностью, из класса Window1 файла Window1.xaml обработчик listEmployees2_SelectionChanged() или закомментируйте содержимое его тела
- Закомментируйте в функции Page2() файла Window1.xaml.cs строку кода присвоения свойству DataContext начального элемента коллекции данных
private void Page2() { // Загружаем данные и назначаем источник привязки employees2 = App.StoreNorthwindDB.ReadTableEmployees(); listEmployees2.SelectedIndex = 0; listEmployees2.Focus(); //gridEmployees2.DataContext = employees2[0]; //listEmployees2.ItemsSource = employees2; //listEmployees2.DisplayMemberPath = "FullName"; listEmployees2.DataContext = employees2; }
- Запустите приложение и испытайте работу вкладки Page2 - она продолжает работать как ни в чем небывало
Что здесь получилось. Коллекцию Employees объектов Employee, которая инкапсулирует извлеченные из БД данные, мы оставили подключенной к DataContext списка ListBox и ее найдет свойство ItemsSource списка. А вот источником привязки для текстовых полей мы назначили свойство SelectedItem списка, которое ассоциируется с элементом коллекции, и разместили эту информацию в свойстве DataContext сетки Grid. Ее найдут привязанные текстовые поля. Фактически мы сделали то же самое, что выполнял ранее процедурный код в обработчике события SelectionChanged списка.
Вдоль дороги лес густой - с Бабами-Ягами!
А в конце дороги той - плаха с топорами!
(В.С. Высоцкий)
Вкладка Page3. Привязка к таблице Employees через объект DataTable инфраструктуры ADO.NET
Здесь побочной работы будет мало, поскольку у нас уже есть метод LoadTableEmployees() в классе StoreNorthwindDB, возвращающий заполненный объект DataTable. Только ранее мы его применяли в объекте-оболочке Employees1, а потом этот объект Employees1 использовали в классе Window1 файла Window1.xaml.cs. Теперь метод LoadTableEmployees() вызовем в классе Window1 и возвращенный им объект-коллекцию DataTable используем в привязке того же самого набора интерфейсных элементов WPF.
Есть одна тонкость в намерении применить уже готовый метод LoadTableEmployees(). Мы сгоряча в нем сделали проверку, чтобы объект DataTable создавался только один раз, из благих намерений - желая разгрузить наш компьютер. Но это значит, что к каким бы ссылкам мы этот метод не применяли, все они будут адресовать один и тот же физически существующий объект DataTable. Пока что это не страшно, поскольку извлеченные из таблицы БД данные мы только просматриваем, а не редактируем. И неважно, через какие замочные скважины (вкладки Pages) мы за этими данными будем подглядывать.
- Создайте в файле Window1.xaml из копии вкладки Page2 (в ее последней версии после проведенных модификаций) новую вкладку Page3 и сделайте в ней необходимые переименования элементов
<!-- Привязка к таблице Employees через объект DataTable из ADO.NET --> <TabItem Header="Page3"> <Grid DataContext="{Binding ElementName=listEmployees3, Path=SelectedItem}" > <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" Name="listEmployees3" ItemsSource="{Binding}" DisplayMemberPath="FullName" /> <TextBlock Grid.Row="1" Margin="0,0,5,0">EmployeeID:</TextBlock> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=EmployeeID, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="2">FullName:</TextBlock> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=FullName, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="3">Address:</TextBlock> <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=Address, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="4">BirthDate:</TextBlock> <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Path=BirthDate, Mode=OneWay}" Focusable="False" /> <TextBlock Grid.Row="5">Region:</TextBlock> <TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Path=Region, Mode=OneWay}" Focusable="False" /> </Grid> </TabItem>
- Добавьте в класс Window1 файла Window1.xaml.cs код присоединения коллекции DataTable к интерфейсным элементам вкладки Page3
#region Вкладка Page3 private void Page3() { // Настраиваем списковый элемент ListBox listEmployees3.SelectedIndex = 0; listEmployees3.Focus(); // Назначаем источником объект-коллекцию данных DataTable listEmployees3.DataContext = App.StoreNorthwindDB.LoadTableEmployees(); } #endregion
Опять для удобства мы применили секцию #region.
- Поместите в обработчик Window_Loaded() класса Window1 вызов функции Page3() для инициализации списка listEmployees3 вкладки Page3
private void Window_Loaded(object sender, RoutedEventArgs e) { Page1(); Page2(); Page3(); }
- Запустите приложение и испытайте работу вкладки Page3 - получим точно такую же функциональность, что и для двух предыдущих вкладок
Разницы нет между чистою правдой и ложью,
Если вначале и ту и другую раздеть!
(В.С. Высоцкий)