Вы зашли как: Гость
26.06.2017 21:38 | dronov_va

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

2.5. Направление привязки



Давайте ещё раз запустим созданное нами приложение Bindings1, но теперь введём какое-либо значение в поле ввода Дюймы. Как только мы перенесём фокус ввода на поле ввода Сантиметры (например, нажав клавишу <Tab>), в последнем появится только что введённое нами значение. Как видим, наша привязка работает не только в "прямом" направлении - от источника к приёмнику, - но и в "обратном" - от приёмника к источнику.

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

В параграфе 2.4 мы упоминали свойство Mode класса Binding. Оно как раз и задаёт, в каком направлении будет работать привязка. А в качестве его значения указывается один из элементов перечисления BindingMode:

  • TwoWay - двунаправленная привязка, уже рассмотренная нами.
    Как только значение свойства приёмника изменяется, оно сразу же переносится в связанное с ним свойство источника. Исключение представляет собой лишь свойство Text: перенос значения выполняется лишь после того, как элемент управления потеряет фокус ввода (как мы и наблюдали ранее);
  • OneWay - однонаправленная привязка, работающая только в "прямом" направлении - от источника к приёмнику. Требует меньше системных ресурсов, чем двунаправленная, поскольку отпадает необходимость следить за изменением значения свойства приёмника и соответственно переносить его в источник;
  • OneTime - одномоментная привязка, отличающаяся от однонаправленной тем, что перенос значения выполняется единожды, сразу после запуска приложения. При работе приложения вообще не требует системных ресурсов, поскольку сразу после переноса значения привязка удаляется.



Указать направление привязки мы можем в знакомом нам диалоговом окне Создание привязки данных. Выведем его таким же образом, как делали это ранее: щёлкнув квадратную кнопочку, расположенную правее нужного элемента управления в панели Свойства, и выберем в появившемся меню пункт Создать привязку данных.

В самом окне развернём группу элементов управления Больше параметров (рис. 7). Станет доступем раскрывающийся список Направление привязки (режим), в котором следует выбрать нужный пункт.


Рис. 7. Диалоговое окно Создание привязки данных (группа Больше параметров развёрнута)



В качестве эксперимента мы можем указать для нашей привязки направление OneWay (то есть создать однонаправленную привязку). В этом случае при занесении нового значения в поле ввода Дюймы (то есть приёмник) это значение не будет перенесено в источник - поле Сантиметры, даже после потери первым полем ввода фокуса.

А привязка с направлением OneTime (одномоментная) в нашем случае вообще бесполезна. Как только приложение запустится, значение из поля ввода Сантиметры - пустая строка - будет перенесено в поле ввода Дюймы, после чего привязка перестанет работать. И что бы мы не вводили в первое поле, второе так и останется пустым.

2.6. Использование преобразователей значений



Кажется, мы писали приложение для преобразования величин из сантиметров в дюймы и наоборот... Тогда почему вводимые нами величины переносятся как есть, без всякого преобразования? Давайте это исправим.


2.6.1. Создание преобразователей значений

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

Преобразователь значения должен представлять собой класс, реализующий интерфейс IValueConverter, что объявлен в пространстве имён Windows.UI.Xaml.Data. Этот интерфейс поддерживает два метода:

  • Convert - выполняет преобразование при переносе в "прямом" направлении - от источника к приёмнику;
  • ConvertBack - выполняет преобразование при переносе в "обратном" направлении - от приёмника к источнику.



Оба этих метода принимают одинаковый набор аргументов:

  • собственно преобразуемое значение - типа System.Object;
  • обозначение типа, в который следует его преобразовать, - заданное в виде соответствующего элемента перечисления System.Type;
  • дополнительный аргумент, который может быть указан в параметрах привязки, - типа System.Object (фактически значение этого аргумента может относиться к любому типу). Он может быть использован, например, для выбора режима преобразования из набора доступных;
  • обозначение языка и культуры, с учётом которой должно быть выполнено преобразование, - в виде строки.



Возвращать эти методы должны уже преобразованное значение. В объявлении интерфейса IValueConverter в качестве типа возвращаемого результата указан System.Object, следовательно, возвращаемое значение может быть любого типа.

Давайте создадим для нашего приложения класс-преобразователь, который будет переводить величины, заданные в сантиметрах, в дюймы и наоборот. Напишем код объявления этого класса в отдельном файле.

Добавить в проект Visual Studio новый элемент, например, файл с программным C#-кодом, можно тремя способами. Во-первых, можно найти в иерархическом списке, что находится в панели Обозреватель решений, "ветвь", представляющую сам проект (в нашем случае это "ветвь" Bindings1 (Universal Windows)), щёлкнуть на ней правой кнопкой мыши, выбрать в появившемся на экране контекстом меню пункт Добавить, а в подменю, что появится следом, - пункт Создать элемент. Во-вторых, можно выбрать пункт Добавить новый элемент меню Проект. В-третьих, можно нажать комбинацию клавиш <Ctrl>+<Shift>+<A>.

После любого из этих действий на экране появится диалоговое окно Добавить новый элемент (рис. 8). В списке, расположенном в середине этого окна, следует выбрать тип добавляемого элемента (в нашем случае - пункт Класс, поскольку мы собираемся добавить файл с программным кодом, в котором запишем объвление нового класса), ввести имя создаваемого файла в поле ввода Имя и нажать кнопку Добавить.


Рис. 8. Диалоговое окно Добавить новый элемент



Если нужно добавить в проект именно файл программного кода, можно поступить проще. Здесь доступны два способа. Первый: щёлкаем правой кнопкой мыши на "ветви" иерархического списка панели Обозреватель решений, что представляет проект, и выбираем пункт Класс подменю Добавить. Второй: выбираем пункт Добавить класс меню Проект. В этом случае в списке открывшегося окна Добавить новый элемент уже будет выбран пункт Класс.

Добавим в проект новый файл программного кода с именем CIConverter.cs. (Именно так мы назовём наш класс преобразователя значения.) Когда этот файл будет создан и открыт, мы увидим, что Visual Studio уже сгенерировала для нас часть кода объявления класса.

Полный код класса CIConverter приведён ниже (выражений импортирования пространств имён, находящиеся в самом начале кода и вставленные туда самой Visual Studio, опущены ради краткости).

class CIConverter : Windows.UI.Xaml.Data.IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, string language)
    {
        double fl = 0;
        if (double.TryParse(value as string, out fl))
        {
            fl = fl / 2.54;
        }
        return fl.ToString();
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, string language)
    {
        double fl = 0;
        if (double.TryParse(value as string, out fl))
        {
            fl = fl * 2.54;
        }
        return fl.ToString();
    }
}



В универсальном приложении, созданном при изучении статьи "Разработка универсальных приложений Windows 10. Самое первое приложение", для преобразования значения, занесённого в поле ввода (как мы уже знаем, оно хранится в свойстве Text в виде строки), в число мы использовали статический метод Parse класса System.Double. Однако здесь есть серьёзная проблема: при попытке преобразовать таким образом строку, хранящую что-либо отличное от числа с плавающей точкой, данный метод генерирует исключение, и выполнение программы останавливается. Нам нужно исключить этот неприятный момент.

Поэтому мы здесь применили статический метод TryParse. Он принимает два аргумента, первый из которых - собственно преобразуемая строка, а второй является выходным и сохраняет число - результат преобразования. Если преобразование выполнилось успешно, метод возвращает true, в противном случае - false.

Исходя из этого, нетрудно понять, как работают оба метода только что написанного нами класса CIConverter. Мы объявляем переменную fl типа double (в терминологии C# так обозначается класс System.Double) и присваиваем ей 0. Далее мы пытаемся преобразовать занесённое в поле ввода строковое значение (предварительно приведя его к строковому типу, ведь, как мы помним, в метод преобразователя оно "поступает" в виде значения типа System.Object) и, если преобразование было успешным, выполняем необходимые вычисления и возвращаем полученный результат.

Отметим, что возвращаемый результат мы явно преобразуем в строку, вызвав метод ToString. Это нужно для того, чтобы результирующее число было выведено на экран с учётом текущих языковых настроек системы (так, в русской Windows числа с плавающей точкой будут выводиться с запятой в качестве десятичного разделителя).

Теперь сохраним проект и переключимся на файл с интерфейсным XAML-кодом начальной страницы. Мы добавим только что написанный нами преобразователь в ресурсы страницы и укажем его в настройках привязки.

К сожалению, Visual Studio не предоставляет никаких инструментов для работы с ресурсами страниц и приложений, поэтому нам придётся занести необходимый XAML-код в описание интерфейса страницы вручную. Этот код приведён ниже; его нужно вставить непосредственно после открывающего тега <Page>.

<Page . . .>

    <Page.Resources>
        <local:CIConverter x:Key="CI"/>
    </Page.Resources>

    . . .
</Page>



Этот код помещает в словарь ресурсов страницы наш класс CIConverter, находящийся в пространстве имён XAML под именем local - это пространство имён нашего приложения - и делает его доступным через ключ "CI".

Далее рекомендуется выполнить сборку решения, чтобы Visual Studio смогла "найти" наш преобразователь и вывести его в диалоговом окне Создание привязки данных. Сборку можно выполнить, выбрав пункт Собрать решение меню Сборка или нажав комбинацию клавиш <Ctrl>+<Shift>+<B>.

После этого выведем диалоговое окно Создание привязки данных для нашей привязки. Здесь нам понадобится раскрывающийся список Конвертер, в котором мы выберем ключ, под которым доступен наш преобразователь (это ключ "CI").

Как только мы выберем в списке Конвертер какой-либо преобразователь, станет доступно поле ввода ConverterParameter. В нём заносится значение дополнительного аргумента, который будет передан методам Convert и ConvertBack класса преобразователя (третий по счёту аргумент этих методов; подробности были описаны ранее).

И, наконец, сохраним проект и запустим приложение на выполнение. В поле ввода Сантиметры введём какое-либо число и поглядим, что появится в поле ввода Дюймы; после этого занесём любое число в поле ввода Дюймы и посмотрим, сколько это будет в сантиметрах. В общем, убедимся, что наше приложение теперь полностью функционально (рис. 9).


Рис. 9. Полностью функциональное приложение Bindings1




2.6.2. Ещё несколько слов о преобразователях значений

Нужно сказать, что необходимость в создании двунаправленной привязки возникает нечасто. Гораздо чаще на практике применяются однонаправленные привязки. Если такая привязка использует преобразователь значений, в нём совершенно не нужно реализовывать преобразование в "обратном" направлении.

В таком случае в теле метода ConvertBack нужно поместить выражение, генерирующее исключание System.NotImplementedException:

class CIConverter : Windows.UI.Xaml.Data.IValueConverter
{
    . . .

    public object ConvertBack(object value, Type targetType,
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}



В интерфейсном XAML-коде преобразователь значения указывается с помощью свойства Converter класса Binding. Значение передаваемому преобразователю дополнительного аргумента (третий по счёту аргумент методов Convert и ConvertBack) можно задать в свойстве ConverterParameter; в случае указания его в интерфейсном коде данное значение трактуется как строка. В свойстве ConverterLanguage может быть указано обозначение языка и культуры, которое будет передано методам Convert и ConvertBack преобразователя четвёртым аргументом; это значение указывается в виде строки.

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

В версии 1607 Windows 10 (Anniversary Update) появилась поддержка преобразования логических величин в элементы перечисления Visibility. Значение true преобразуется в элемент Visible, а false - в Collapsed. Это преобразование выполняется самой платформой UWP; нам для его выполнения никаких действий предпринимать не нужно.

Внимание!
Описанная ранее возможность не будет работать в более ранних версиях Windows 10.

2.7. Программное создание привязки



Иногда может оказаться полезным создать привязку программно, в функциональном C#-коде приложения. Это может пригодиться, если нужно выполнять привязку элемента-приёмника к разным источникам в зависимости от каких-то условий или использовать один и тот же объект привязки для разных элементов.

Программное создание привязки выполняется в три этапа.

На первом этапе создаётся объект класса Binding. Его конструктору не передаётся никаких аргументов.

На втором этапе указываются параметры созданной привязки: источник, связываемое свойство источника, направление привязки и преобразователь значения, если это необходимо. Эти параметры задаются с применением изученных нами ранее свойств класса Binding:

  • ElementName - имя элемента-источника - в виде строки;
  • Path - связываемое свойство элемента-источника - в виде объекта класса PropertyPath. Строковое имя свойства задаётся в конструкторе этого класса единственным аргументом;
  • Mode - направление привязки - в виде элемента перечисления BindingMode;
  • Converter - преобразователь значения - в виде объекта соответствующего класса;
  • ConverterParameter - дополнительный аргумент для преобразователя значения - может быть любого типа;
  • ConverterLanguage - обозначение языка и культуры - в виде строки.



На третьем этапе привязка соотносится с элементом-приёмником и его свойством. Для этого применяется метод SetBinding, вызываемый у приёмника и принимающий два аргумента:

  • связываемое свойство - в виде обозначения свойства зависимости;
  • привязка - в виде только что созданного объекта класса Binding.



Вот пример создания привязки для нашего приложения в функциональном коде (предполагается, что поле ввода - приёмник имеет имя txtInches):

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        . . .
       
        Binding b = new Binding();
        b.ElementName = "txtCentimetres";
        b.Path = new PropertyPath("Text");
        b.Mode = BindingMode.TwoWay;
        b.Converter = new CIConverter();
        txtInches.SetBinding(TextBox.TextProperty, b);
    }
}



Чтобы этот код успешно работал, нам, помимо указания имени для второго поля ввода, понадобится также удалить привязку, ранее созданную с применением визуальных инструментов Visual Studio, в XAML-коде. Сделать это можно, щёлкнув на всё той же квадратной кнопке, что расположена правее поля ввода Text панели Свойства, и выбрав в появившемся меню пункт Сбросить.

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








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

Комментарии

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

По теме

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