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

Привязка WPF к реляционным данным

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >

Вкладка Page3. Повторение предыдущей задачи вручную

В двух предыдущих примерах мы пользовались типом набора данных, который автоматически сгенерировал мастер оболочки Data Source Configuration Wizard по нашим настройкам. В данном примере мы все настройки выполним сами в процедурном коде, опираясь на инфраструктуру объекта DataSet.

Объект DataSet кроме коллекции Tables объектов DataTable содержит еще и свойство Relations, которое может адресовать экземпляр класса System.Data.DataRelationCollection. Коллекция Relations ожидает объекты DataRelation, в которых можно определять отношения между таблицами коллекции Tables. Следовательно, объект DataSet можно рассматривать как набор таблиц и отношений. Минимальное количество как таблиц, так и отношений в DataSet равно нулю.

В данном примере мы заполним коллекцию Tables таблицами Customers, Orders и виртуальной таблицей представления Order Details Extended, установим вручную отношения между таблицами, затем привяжем набор к пользовательскому интерфейсу WPF. В итоге должен получиться такой же результат, что и для типизированного набора данных.

  • В панели Solution Explorer щелкните правой кнопкой мыши на файле Northwind.mdb и выполните команду Open With, затем Microsoft Office Access ( если он у вас установлен!)

  • Установите вкладку Запросы в СУБД Access
  • Для записи Order Details Extended вызовите контекстное меню и выполните команду Конструктор
  • Щелкните правой кнопкой мыши на заголовке (или свободном месте) окна Order Details Extended и выполните команду Режим SQL

В результате мы получим строку SQL -запроса, которая формирует виртуальную таблицу представления Order Details Extended (ранее уже приводилась)

SELECT DISTINCTROW [Order Details].OrderID, [Order Details].ProductID, Products.ProductName, 
[Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount, 
CCur([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100 AS ExtendedPrice
FROM Products INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID
ORDER BY [Order Details].OrderID;
Листинг .
  • В панели Solution Explorer для узла References выполните команду Add Reference и добавьте к проекту ссылку на библиотечную сборку System.Configuration.dll

  • В панели Solution Explorer для корня проекта DataBindingRelation выполните команду Add/New Item и добавьте к проекту конфигурационный файл App.config
  • Заполните файл App.config следующей разметкой
<?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>
  • Добавьте в файл Window1.xaml.cs следующий процедурный код
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
    
// Добавили пространства имен типизированных классов
using DataBindingRelation.Data;
using DataBindingRelation.Data.NorthwindDataSetTableAdapters;
using DS2 = DataBindingRelation.Data.NorthDataSetTableAdapters;// Псевдоним
    
// Подключение пространств имен инфраструктуры ADO.NET
using System.Data;
using System.Data.OleDb;
    
namespace DataBindingRelation
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
    
            Page1();
            Page2();
            Page3();
        }
    
        #region Вкладка Page1
        void Page1()
        {
            // Создание экземпляров сгененированных классов
            NorthwindDataSet dataSet = new NorthwindDataSet();
            CustomersTableAdapter custAdap = new CustomersTableAdapter();
            OrdersTableAdapter ordAdap = new OrdersTableAdapter();
            Order_Details_ExtendedTableAdapter ord_det_extAdap =
                new Order_Details_ExtendedTableAdapter();
    
            // Потабличное наполнение экземпляра типизированного набора данных
            custAdap.Fill(dataSet.Customers);
            ordAdap.Fill(dataSet.Orders);
            ord_det_extAdap.Fill(dataSet.Order_Details_Extended);
    
            // Подключение набора данных к интерфейсу
            grid1.DataContext = dataSet.Customers;
        }
        #endregion
    
        #region Вкладка Page2
        void Page2()
        {
            // Создание экземпляров сгененированных классов
            NorthDataSet dataSet = new NorthDataSet();
            DS2.CustomersTableAdapter custAdap = new DS2.CustomersTableAdapter();
            DS2.OrdersTableAdapter ordAdap = new DS2.OrdersTableAdapter();
            DS2.Order_Details_ExtendedTableAdapter ord_det_extAdap =
                new DS2.Order_Details_ExtendedTableAdapter();
    
            // Потабличное наполнение экземпляра типизированного набора данных
            custAdap.Fill(dataSet.Customers);
            ordAdap.Fill(dataSet.Orders);
            ord_det_extAdap.Fill(dataSet.Order_Details_Extended);
    
            // Подключение набора данных к интерфейсу
            grid2.DataContext = dataSet.Customers;
        }
        #endregion
    
        #region Вкладка Page3
        void Page3()
        {
            // Извлекаем в поле строку соединения из файла App.config
            String connectionString = System.Configuration.
                ConfigurationManager.ConnectionStrings["MyNorthwind"].ConnectionString;
    
            DataSet dataSet = new DataSet();// Создаем множественный набор данных
    
            // Заполняем множественный набор данных из БД
            using (OleDbConnection conn = new OleDbConnection(connectionString))
            {
                OleDbCommand selectCommand = conn.CreateCommand();
                OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
    
                // Загружает всю таблицу Customers
                selectCommand.CommandText = "SELECT * FROM Customers";
                adapter.Fill(dataSet, "Customers");
    
                // Загружает всю таблицу Orders
                selectCommand.CommandText = "SELECT * FROM Orders";
                // Загружаем и сразу этой порции данных назначаем имя в наборе
                adapter.Fill(dataSet, "Orders");
    
                // Загружаем представление по SQL-запросу
                selectCommand.CommandText = @"SELECT DISTINCTROW [Order Details].OrderID, [Order Details].ProductID,
   Products.ProductName,
                    [Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount,
                    CCur([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100 AS ExtendedPrice 
                    FROM Products INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID 
                    ORDER BY [Order Details].OrderID";
                adapter.Fill(dataSet, "Order_Details_Extended");
            }
    
            // Создание отношения между таблицами Customers и Orders
            dataSet.Relations.Add("CustomersOrders",
                dataSet.Tables["Customers"].Columns["CustomerID"],
                dataSet.Tables["Orders"].Columns["CustomerID"]);
    
            // Создание отношения между таблицами Orders и Order_Details_Extended
            // Немного другим способом
            DataColumn parentColumn = dataSet.Tables["Orders"].Columns["OrderID"];
            DataColumn childColumn = dataSet.Tables["Order_Details_Extended"].Columns["OrderID"];
            DataRelation relation = new DataRelation(
                "Orders_Order_Details_Extended",
                parentColumn, childColumn);
            dataSet.Relations.Add(relation);
    
            // Подключение набора данных к интерфейсу
            grid3.DataContext = dataSet.Tables["Customers"];
        }
        #endregion
    }
}
  • В контейнер TabControl добавьте копию вкладки Page2 и переименуйте в ней первую сетку на grid3, чтобы разметка стала такой
<!-- Привязка к нетипизированному DataSet -->
            <TabItem Header="Page3">
                <Grid Name="grid3">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="2*" />
                            <ColumnDefinition Width="1.5*" />
                            <ColumnDefinition Width="2*" />
                        </Grid.ColumnDefinitions>
                        
                        <TextBlock Grid.Column="0" HorizontalAlignment="Center">ContactName</TextBlock>
                        <ListBox Grid.Row="1" Grid.Column="0"
                            Margin="0,0,0,3"
                            ScrollViewer.VerticalScrollBarVisibility="Auto"
                            ItemsSource="{Binding}"
                            DisplayMemberPath="ContactName"
                            IsSynchronizedWithCurrentItem="True"
                            />
                        
                        <TextBlock Grid.Column="1" HorizontalAlignment="Center">OrderDate</TextBlock>
                        <ListBox Grid.Row="1" Grid.Column="1"
                            Margin="0,0,0,3"
                            ScrollViewer.VerticalScrollBarVisibility="Auto"
                            ItemsSource="{Binding Path=CustomersOrders}"
                            DisplayMemberPath="OrderDate"
                            IsSynchronizedWithCurrentItem="True"
                            />
                        
                        <TextBlock Grid.Column="2" HorizontalAlignment="Center">ProductName</TextBlock>
                        <ListBox Grid.Row="1" Grid.Column="2"
                            Margin="0,0,0,3"
                            ScrollViewer.VerticalScrollBarVisibility="Auto"
                            ItemsSource="{Binding Path=CustomersOrders/Orders_Order_Details_Extended}"
                            DisplayMemberPath="ProductName"
                            />
                    </Grid>
                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        
                        <TextBlock Grid.Row="0" Margin="0,0,5,0">ShipName:</TextBlock>
                        <TextBox Grid.Row="0" Grid.Column="1" 
                            Text="{Binding Path=CustomersOrders/ShipName, Mode=OneWay}"
                            Focusable="False"
                            Margin="5,0,0,0"
                            />
                        
                        <TextBlock Grid.Row="1">ShipAddress:</TextBlock>
                        <TextBox Grid.Row="1" Grid.Column="1" 
                            Text="{Binding Path=CustomersOrders/ShipAddress, Mode=OneWay}"
                            Focusable="False"
                            Margin="5,0,0,0"
                            />
                        
                        <TextBlock Grid.Row="2">ShipCity:</TextBlock>
                        <TextBox Grid.Row="2" Grid.Column="1" 
                            Text="{Binding Path=CustomersOrders/ShipCity, Mode=OneWay}"
                            Focusable="False"
                            Margin="5,0,0,0"
                            />
                        
                        <TextBlock Grid.Row="3">ShipCountry:</TextBlock>
                        <TextBox Grid.Row="3" Grid.Column="1" 
                            Text="{Binding Path=CustomersOrders/ShipCountry, Mode=OneWay}"
                            Focusable="False"
                            Margin="5,0,0,0"
                           />
                    </Grid>
                </Grid>
            </TabItem>
  • Запустите приложение - получим результат, в точности совпадающий с двумя предыдущими

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >
Алексей Бабушкин
Алексей Бабушкин

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

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

Юрий Макушин
Юрий Макушин
Россия, Москва, РЭА им. Плеханова, 2004