Вы зашли как: Гость
10.07.2017 15:53 | dronov_va

Третья часть статьи, посвящённой привязке данных и её использованию при разработке универсальных приложений Windows 10.

3. Привязка внутренних объектов



Немногим сложнее выполнить привязку внутренних объектов, то есть объектов классов, объявленных самим разработчиком приложения.

Создадим в Visual Studio новый проект с именем Bindings2. Это будет другая редакция приложения для преобразования величин из сантиметров в дюймы. Ради простоты мы сделаем только "прямое" преобразование.

Разместим на начальной странице те же самые элементы управления, что и в случае первого приложения такого рода, с теми же самыми параметрами. (Проще всего сделать это, скопировав интерфейсный XAML-код из файла MainPage.xaml приложения Bindings1.) Никаких привязок пока создавать не будем.


3.1. Объявление внутреннего класса

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

Добавим в проект новый файл программного кода с именем CIData.cs. Запишем в нём объявление класса CIData, приведённое ниже.

public class CIData
{
    private double __centimetres = 0;

    public string Centimetres
    {
        get
        {
            return this.__centimetres.ToString();
        }
        set {
            double fl = 0;
            if (double.TryParse(value, out fl))
            {
                if (this.__centimetres != fl)
                {
                    this.__centimetres = fl;
                }
            }
        }
    }

    public string Inches
    {
        get {
            return (this.__centimetres / 2.54).ToString();
        }
    }
}



Отметим здесь следующие примечательные детали:

  • Внутренний класс мы сделали открытым (публичным). Это нужно для того, чтобы платформа UWP впоследствии смогла получить к нему доступ, создать на его основе объект и использовать последний в качестве источника.
  • Мы объявили закрытое (частное) поле __centimetres, в котором будет храниться величина в сантиметрах. Для этого поля мы указали тип данных double (число с плавающей точкой).
  • Мы объявили доступное и для чтения, и для записи строковое свойство Centimetres, которое потом свяжем со свойством Text поля ввода txtCentimetres. Его функция-геттер просто преобразует значение из поля __centimetres в строку. А функция-сеттер получит значение в сантиметрах, занесённое пользователем, преобразует его в число с плавающей точкой, проверит, не совпадает ли оно с тем, что хранится в поле __centimetres, и, если это так, занесёт его в это поле.

    На заметку
    В принципе, создавать в этом свойстве геттер необязательно. Можно оставить лишь функцию-сеттер - тогда свойство станет доступным только для записи. Однако в этом случае будет невозможно создать привязку вторым способом. (О двух способах создания привязки будет рассказано позже.)
  • Ещё мы объявили доступное только для чтения свойство Inches, которое позже свяжем со свойством Text второго поля ввода. Функция-геттер этого свойства преобразует величину в сантиметрах, хранящуюся в поле __centimetres, в дюймы и превратит его в строку. (Эта строка потом будет выведена во втором поле ввода.)



Сохраним проект и выполним сборку решения.

Всё готово для создания привязки. Которую мы можем создать двумя способами: первый - попроще, второй - посложнее.


3.2. Задание объекта-источника

В зависимости от способа создания привязки её источник также задаётся по-разному: для первого способа - непосредственно, для второго - в ресурсах.


3.2.1. Первый способ: непосредственное задание источника

При создании привязки первым способом источник задаётся непосредственно. Это можно сделать, пользуясь исключительно визуальными средствами Visual Studio.

Однако здесь есть небольшая проблема. Дело в том, что для каждой привязки, созданной с применением простого способа, будет создан отдельный внутренний объект. В нашем случае, если мы укажем класс CIData в качестве источника привязки для каждого из полей ввода, для каждого из них будет создан отдельный объект этого класса. Как следствие, наше приложение не будет работать, как мы планировали.

Поэтому мы укажем источник не непосредственно для полей ввода, а для их родителя - контейнера Grid. При запуске приложения UWP, не найдя указания на источник непосредственно в приёмниках, будет искать его в их родителе, потом - в родителе родителя и т. д., пока поиски не увенчаются успехом.

В визуальном редакторе выберем контейнер, для чего щёлкнем на месте, не занятом никакими элементами интерфейса. Также можно обратиться к расположенному в нижней половине редактору XAML-кода и установить текстовый курсор на открывающий тег <Grid>. В панели Свойства найдём категорию Общие, развернём её и отыщем свойство DataContext - именно в нём указывается источник.

Правее имени этого поля ввода видна кнопка Создать. Нажмём её - и на экране появится диалоговое окно Выбор объекта (рис. 10).


Рис. 10. Диалоговое окно Выбор объекта



Это окно почти полностью занимает большой иерархический список классов, доступных в нашем приложении; это как классы, созданные нами, так и те, что входят в состав платформы UWP. В верхней части окна находится поле ввода Поиск объектов; если ввести в него часть имени класса, в списке будут показаны только те классы, чьи имена содержат введённую часть.

Выберем в этом списке пункт Binding2 > Binding2 > CIData, то есть наш класс. После чего нажмём кнопку ОК, чтобы подтвердить сделанный нами выбор.

Мы сразу заметим, что в панели Свойства, сразу после имени свойства DataContext, появится имя выбранного нами класса.

Давайте посмотрим на XAML-код, устанавливающий источник для контейнера Grid:

<Grid . . .>
    <Grid.DataContext>
        <local:CIData/>
    </Grid.DataContext>
    . . .
</Grid>



Здесь в качестве значения свойства DataContext (которое, как мы знаем, и задаёт источник) устанавливается объект класса CIData, объявленного в пространстве имён приложения.

Этот способ можно применить, если к источнику требуется привязать всего один приёмник или несколько приёмников, находящихся в одном контейнере.


3.2.2. Второй способ: задание источника в ресурсах

Описанную ранее проблему также можно избежать, создав привязку вторым способом. Он заключается в том, что источник превращается в ресурс страницы или приложения, а привязка приёмников выполняется уже к нему. (С ресурсами страницы мы уже немного знакомы - использовали, когда создавали преобразователь значения.) При запуске приложения на основе превращённого в ресурс класса-источника будет создан один-единственный внутренний объект, и все приёмники окажутся связанными с ним.

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

В редакторе XAML-кода, что находится в нижней части окна, найдём открывающий тег Page и вставим непосредственно после него код, создающий ресурс:

<Page . . .>

    <Page.Resources>
        <local:CIData x:Key="CID"/>
    </Page.Resources>

    . . .
</Page>



Здесь мы помещаем наш класс CIData в словарь ресурсов страницы и указываем для него ключ "CID".


3.3. Создание привязки

Указав источник привязки, можно приступать к формированию самой привязки.


3.3.1. Первый способ: источник задан непосредственно

Если источник задан первым способом - непосредственно, - привязка формируется, опять же, исключительно визуальными средствами среды разработки.

Сначала создадим привязку свойства Text поля ввода txtCentimetres, которое выступит приёмником, к свойству Centimetres источника.

Выберем вышеупомянутое поле ввода, в панели Свойства найдём свойство Text, щёлкнем на знакомой нам квадратной кнопке справа и выберем в появившемся меню пункт Создать привязку данных. Когда на экране возникнет диалоговое окно Создание привязки данных, в раскрывающемся списке Тип привязки выберем пункт Контекст данных (русский перевод имени свойства DataContext). В правом иерархическом списке появится перечень свойств класса CIData.

Выберем в этом списке свойство Centimetres. И, поскольку хотим, чтобы значение, занесённое в поле ввода txtCentimetres, переносилось в свойство Centimetres источника (то есть должен выполнять ещё и перенос в "обратном" направлении), развернём группу Больше параметров и выберем в раскрывающемся списке Направление привязки (режим) пункт TwoWay.

Проверим, всё ли правильно мы ввели (рис. 11). И нажмём кнопку ОК.


Рис. 11. Параметры привязки



Посмотрим на XAML-код, создающий привязку:

<TextBox x:Name="txtCentimetres" . . . Text="{Binding Centimetres, Mode=TwoWay}"/>



Всё нам уже знакомо. (За тем исключением, что не указано свойство ElementName - имя связываемого элемента управления, но оно и понятно.)

Точно таким же образом создадим привязку второго поля ввода к свойству Inches источника. И не забудем указать направление привязки OneWay, так как нам нужно выполнять перенос значения только в "прямом" направлении.


3.3.2. Второй способ: источник задан в ресурсах

Если источник задан в ресурсах, нам придётся ввести XAML-кад, создающий привязку, вручную. К сожалению, другого способа сделать это нет.

Мы уже знаем, что программная платформа сама создаст объект на основе класса, указанного в составе ресурсов. И этот объект будет присутствовать в одном-единственном числе. Следовательно, мы можем привязать оба поля ввода прямо к нему.

Найдём строку XAML-кода, создающего поле ввода txtCentimetres. Добавим в него следующий фрагмент, который, собственно, создаст привязку для свойства Text:

<TextBox . . . Text="{Binding Centimetres, Mode=TwoWay, Source={StaticResource CID}}"/>



Здесь применяется уже знакомое нам объектное синтаксическое расширение Binding. Указано связываемое свойство Centimetres, направление TwoWay и - посредством свойства Source - источник. Обратим внимание, как указывается источник, являющийся ресурсом, - для этого также применяется объектное синтаксическое расширение, только другое - StaticResource, за которым записывается ключ ресурса.

Создадим привязку к свойству Text второго поля ввода самостоятельно. Только не забудем указать в качестве имени связываемого свойства Inches, а в качестве направления привязки - OneWay.


Дополнительные материалы





Владимир Дронов, MSInsider.ru Team
Май 2017

Комментарии

Комментариев нет...
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
74.18 +0.04
Акции торгуются с 17:30 до 00:00 по Москве
Мы на Facebook
Мы ВКонтакте
Все права принадлежат © MSInsider.ru (ex TheVista.ru), 2017
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.313 секунд (Общее время SQL: 0.238 секунд - SQL запросов: 31 - Среднее время SQL: 0.00767 секунд))