Опубликован: 08.07.2011 | Доступ: свободный | Студентов: 1772 / 93 | Оценка: 4.15 / 4.08 | Длительность: 15:28:00
Лекция 3:

Базовые инструменты WPF

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

Привязка данных в WPF

Основы привязки данных

В общем случае, привязкой данных ( data binding ) называется методика связывания элементов управления и интерфейсных элементов с данными [ 4 ] , [ 6 ] , [ 8 ] , [ 9 ] . Привязка данных применяется для отображения некоторой информации из объекта-источника в пользовательском интерфейсе – свойстве целевого объекта. Кроме отображения информации в элементе управления возникает задача изменения отображаемых данных. При этом необходимо проводить синхронизацию данных объекта-источника и свойства целевого объекта при изменении любого из них.

Привязка данных представляет собой отношение, которое определяет для WPF какую информацию необходимо извлечь из объекта-источника и использовать её для установки свойства целевого объекта. Целевое свойство должно обязательно быть свойством зависимостей и, как правило, принадлежать элементу WPF. Объект-источник может быть объектом данных приложения – общедоступным свойством класса, элементом WPF, объектом данных ADO.NET.

При проектировании приложений возникает задача создания привязки для некоторых свойств объектов и элементов интерфейса. Такая привязка возможна только в том случае, если свойство объекта-источника является общедоступным.

Для изучения технологии привязки данных рассмотрим пример, в котором ставится следующая задача. Необходимо разработать интерфейсный элемент для ввода параметра, который представляется вещественным числом (тип с плавающей точкой) в диапазоне от 0 до 1. Функциональность интерфейсного элемента должна предусматривать проверку достоверности вводимой информации.

Привязка данных, не являющихся элементами WPF

Создадим проект для интерфейсного элемента ввода данных ( рис. 3.1).

Окно ввода вещественных чисел

Рис. 3.1. Окно ввода вещественных чисел

XAML-описание окна Window1 приведен ниже:

<Window x:Class="Wpf_Primer1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Ввод вещественного числа" Height="140" Width="300">
    <Grid Name="gridPrimir" Height="85">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Label Margin="3,3,3,15" Name="label1">Параметр</Label>
        <TextBox Grid.Column="1" Margin="5,5,28,15" Name="textBox1" />
        <Button Grid.Column="1" Grid.Row="1" Margin="5,5,28,12" Name="button1" 
                Click="button1_Click">Проверить</Button>
    </Grid>
</Window>

Код класса Window1:

using System;
using System.Windows;
using System.Windows.Controls;
namespace Wpf_Primer1
{
    public partial class Window1 : Window
    {
        public static float Factor { get; set; }
       
        public Window1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(Factor.ToString(), "Проверка значения параметра");
        }
    }
}

Свойство Factor класса Window1 необходимо для приема вводимого вещественного числа и его целесообразно сделать статическим для доступа из других классов приложения. Элемент TextBox используется для ввода вещественных чисел с плавающей точкой. Вводимое число должно передаваться свойству Factor. Кнопка button1 введена в форму для инициации проверки – вывода сообщения со значением свойства Factor. У нас встает задача привязки свойства Factor к свойству зависимостей Text элемента TextBox.

В общем случае для привязки к объекту, не являющемуся элементом, можно использовать следующие свойства:

  • Source, которое указывает на объект-источник, поставляющий данные;
  • RelativeSource, которое указывает на объект-источник, используя объект RelativeSource, позволяющий базировать ссылку на текущем элементе;
  • DataContent, которому необходимо присвоить значение объекта-источника для текущего или более высокого элемента в дереве визуальных элементов приложения.

В нашем случае целесообразно использовать свойство RelativeSource. Для реализации привязки введем изменение в XAML-код элемента TextBox, добавив описание свойства Text:

<TextBox Grid.Column="1" Margin="5,5,28,15" Name="textBox1" 
             Text="{Binding Path = Factor, RelativeSource = 
             {RelativeSource FindAncestor, AncestorType = {x:Type Window}}}"/>

В выражении привязки данных применяется расширение разметки XAML, которое заключается в фигурные скобки. Выражение начинается со слова Binding означающее, что создается экземпляр класса System.Windows.Data.Binding. Свойству Path присваивается значение объекта-источника, в нашем случае это свойство Factor. Объект RelativeSource задается с помощью расширенной разметки. Режим FindAncestor является значением перечисления RelativeSourceMode и определяет выражение привязки к родительскому элементу в визуальном дереве интерфейсного элемента. Кроме значения FindAncestor перечисление RelativeSourceMode может задавать следующие режимы:

  • Self - для привязки к другому свойству того же элемента;
  • PreviousData – для привязки к предыдущему элементу данных в привязываемых к данным списке;
  • TemplateParent – для привязывания к элементу, к которому применен шаблон.

Свойство AncestorType определяет элемент в визуальном дереве, где содержится объект-источник. В нашем случае свойство Factor является членом класса Window1 элемента Window.

Протестируем созданное приложение. При вводе строки 0.1, что соответствует формату вещественного числа, получаем результат проверки вещественное число 0,1 ( рис. 3.2).

Проверка ввода строки "0.1"

Рис. 3.2. Проверка ввода строки "0.1"

При выводе вещественное число преобразуется к строковому представлению методом ToString():

MessageBox.Show(Factor.ToString(), "Проверка значения параметра");

В результате этого десятичная точка заменяется на запятую и в окне "Проверка значения параметра" выводится строка "0,1", а не введенная "0.1":

При вводе строки "0,1", что не соответствует формату вещественного числа с плавающей точкой, получаем в результате преобразования по умолчания целое число "1" ( рис. 3.3).

Проверка ввода строки "0,1"

Рис. 3.3. Проверка ввода строки "0,1"

При вводе недопустимого символа, получаем в результате проверки целое число 1, которое было присвоено свойству Factor в предыдущем сеансе тестирования программы ( рис. 3.4).

Проверка ввода недопустимого символа

Рис. 3.4. Проверка ввода недопустимого символа

Результаты тестирования разработанной программы показывают, что при вводе корректного представления вещественного числа программа работает правильно, а при вводе недопустимых символов или нарушении формата вещественного числа (ввод запятой вместо точки) программа выдает неправильный результат. Это определяет необходимость проверки достоверности ввода для предотвращения некорректных значений.

При корректном вводе данных мы убедились, что взаимодействие между свойством Text элемента TextBox и свойством Factor класса Window1 правильно поддерживается созданной привязкой, то есть информация от целевого объекта передается к объекту-источнику.

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >
Александр Петров
Александр Петров

При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. 
Вопрос, как отследить и отключить добавление элемента в Items?

Максим Спиридонов
Максим Спиридонов

В пятой лекции на второй странице в компиляторе выскакивает ошибка в строчке :

ObjectQuery<Employee> employees = DataEntitiesEmployee.Employees;

Ошибка CS0029

Не удается неявно преобразовать тип "System.Data.Entity.DbSet<WpfApplProject.Employee>" в "System.Data.Entity.Core.Objects.ObjectQuery<WpfApplProject.Employee>".

в using прописал все как положено, здесь похоже именно с преобразованием типов проблемы