Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2009 / 47 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Лекция 2:

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

< Лекция 1 || Лекция 2: 123456 || Лекция 3 >

Добавление вычислимого столбца

Сейчас вычислимый столбец тоже можно добавить в нужную коллекцию объектной модели набора, но поскольку данные уже заполнены, придется заново перебрать все строки коллекции и присвоить придуманному столбцу требуемыми значениями. А можно поступить по другому: добавить в коллекцию набора ДО ЕГО ЗАПОЛНЕНИЯ новый столбец, настроить его схему требуемым образом, а потом загрузить коллекцию данными из хранилища. Вычислимый столбец сразу будет пересчитан налету и заполнен данными. При этом выражение 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 - текстовые поля перестают отслеживать выделенные позиции списка: список и коллекция прекратили синхронную работу

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

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