29
Общие сведения о связывании данных Привязка данных Windows Presentation Foundation (WPF) обеспечивает простой и согласованный способ представления данных и взаимодействия с ними в приложениях. Можно связывать элементы с данными из разнообразных источников данных в форме объектов common language runtime (CLR) и XML.Элементы управления ContentControl, например Button, элементы управления ItemsControl, например ListBox и ListView обладают встроенной возможностью включения гибких стилей для отдельных элементов данных и коллекций элементов данных. Представления сортировки, фильтрации и группировки могут быть организованы поверх данных. Функциональные возможности связывания данных в WPF имеют несколько преимуществ перед традиционными моделями, включая широкий диапазон свойств, которые внутренне поддерживают связывание данных, гибкое представление UI данных и четкое разделение бизнес-логики и UI. В этом разделе сначала будут рассмотрены основные фундаментальные понятия связывания данных в WPF, а затем использование класса Binding и других возможностей связывания данных. В этом разделе содержатся следующие подразделы. Понятие о привязке к данным Основные понятия связывания данных Создание привязки Преобразование данных Привязка к коллекциям Шаблоны данных Проверка данных Механизм отладки Связанные разделы Понятие о привязке к данным Привязка к данным является процессом, который устанавливает связь между приложением UI и бизнес-логикой. Если привязка имеет правильные параметры и данные предоставляют правильные уведомления, то при изменении значений данных в элементах, которые привязаны к данным, автоматически отражаются изменения. Привязка к данным может также означать, что если внешнее представление данных в элементе изменяется, то базовые данные могут автоматически обновляться для отражения изменений. Например если пользователь изменяет значение в элементе TextBox, базовое значение данных автоматически обновляется, чтобы отразить это изменение. Привязка к данным обычно используется для того, чтобы поместить сервер или локальную конфигурацию данных в формы или другие элементы управления UI. В WPF эта концепция расширяется и уже включает привязку широкого диапазона свойств к различным источникам данных. В WPF, свойства зависимостей элементов могут быть привязаны к объектам CLR

General Facts About Binding

Embed Size (px)

Citation preview

Page 1: General Facts About Binding

Общие сведения о связывании данных

Привязка данных Windows Presentation Foundation (WPF) обеспечивает

простой и согласованный способ представления данных и взаимодействия с

ними в приложениях. Можно связывать элементы с данными из

разнообразных источников данных в форме объектов common language

runtime (CLR) и XML.Элементы управления ContentControl, например Button,

элементы управления ItemsControl, например ListBox и ListView обладают

встроенной возможностью включения гибких стилей для отдельных

элементов данных и коллекций элементов данных. Представления

сортировки, фильтрации и группировки могут быть организованы поверх

данных.

Функциональные возможности связывания данных в WPF имеют несколько

преимуществ перед традиционными моделями, включая широкий диапазон

свойств, которые внутренне поддерживают связывание данных, гибкое

представление UI данных и четкое разделение бизнес-логики и UI.

В этом разделе сначала будут рассмотрены основные фундаментальные

понятия связывания данных в WPF, а затем — использование

класса Binding и других возможностей связывания данных.

В этом разделе содержатся следующие подразделы.

Понятие о привязке к данным

Основные понятия связывания данных

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

Преобразование данных

Привязка к коллекциям

Шаблоны данных

Проверка данных

Механизм отладки

Связанные разделы

Понятие о привязке к данным

Привязка к данным является процессом, который устанавливает связь между

приложением UI и бизнес-логикой. Если привязка имеет правильные

параметры и данные предоставляют правильные уведомления, то при

изменении значений данных в элементах, которые привязаны к данным,

автоматически отражаются изменения. Привязка к данным может также

означать, что если внешнее представление данных в элементе изменяется, то

базовые данные могут автоматически обновляться для отражения

изменений. Например если пользователь изменяет значение в

элементе TextBox, базовое значение данных автоматически обновляется,

чтобы отразить это изменение.

Привязка к данным обычно используется для того, чтобы поместить сервер

или локальную конфигурацию данных в формы или другие элементы

управления UI. В WPF эта концепция расширяется и уже включает привязку

широкого диапазона свойств к различным источникам данных. В WPF,

свойства зависимостей элементов могут быть привязаны к объектам CLR

Page 2: General Facts About Binding

(включая объекты ADO.NET или объекты, связанные с веб-службами и веб-

свойствами), и к данным XML.

Привязку данных можно рассмотреть на примере следующего приложения

UIсо страницы Примера привязки данных (содержимое страницы может

отображаться на английском языке):

Выше показан интерфейс UI приложения, который отображает список лотов

аукциона. Приложение демонстрирует следующие возможности связывания

данных:

Содержимое ListBox привязано к коллекции

объектов AuctionItem. Объект AuctionItem имеет такие свойства

как DescriptionStartPriceStartDate,Category, SpecialFeatures и т.д.

Данные (объекты AuctionItem), отображаемые в ListBox, используются в

шаблоне таким образом, что для каждого элемента показаны его

описание и текущая цена. Это делается с помощью DataTemplate. Кроме

того, внешний вид каждого элемента зависит от

значенияSpecialFeaturesотображаемого объекта AuctionItem. Если

значением SpecialFeatures объекта AuctionItem является Color, элемент

имеет синюю границу. Если значением является Highlight, элемент

имеет оранжевые границы и помечается звездочкой. Раздел Создание

шаблонов данных содержит сведения о создании шаблонов данных.

Пользователь может группировать, фильтровать или сортировать

данные с помощью предоставленных элементов CheckBox. На рисунке,

приведенном выше, выбраны элементы CheckBox "Группировать по

категориям" и "Сортировать по категориям и дате". Обратите внимание,

Page 3: General Facts About Binding

что данные группируются по категориям продуктов, а имена категорий

приводятся в алфавитном порядке. Из рисунка трудно заметить, что

элементы в каждой категории также сортируются по начальной

дате. Это делается с использованием представления коллекции. В

разделе Привязка к коллекциям обсуждаются представления коллекций.

Когда пользователь выбирает элемент, ContentControl отображает

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

"основной/подробности". В разделе Скрипт

"основной/подробности" содержатся сведения об этом типе скрипта

привязки.

Типом свойства StartDate является DateTime, который возвращает дату,

включая время с точностью до миллисекунды. В этом приложении

пользовательский преобразователь был использован таким образом,

чтобы дата отображалась в укороченном формате. В

разделеПреобразование данных представлены сведения о

преобразователях.

При нажатии кнопки Добавить продукт, появляется следующая форма:

Пользователь может изменить поля формы, просмотреть список продуктов с

помощью панелей краткого предварительного просмотра и подробного

предварительного просмотра и нажать кнопку Отправить для добавления

данных нового продукта. К новой записи будут применимы все

существующие функциональные возможности группировки, фильтрации и

сортировки. В этом конкретном случае элемент, введенный на приведенном

выше рисунке, будут отображаться как второй элемент в

категории Компьютер.

На этом рисунке не показана логика проверки, предоставленная

в TextBoxStart Date. Если пользователь вводит недопустимую дату

Page 4: General Facts About Binding

(недопустимый формат или прошедшую дату), он будет уведомлен ToolTip и

красным восклицательным знаком после TextBox. В разделе Проверка

данных обсуждается создание логики проверки.

Прежде чем перейти в другим описанным выше возможностям связывания

данных, в следующем разделе обсудим основные понятия, важные для

понимания связывание данных WPF.

Основные понятия связывания данных

Этот подраздел состоит из следующих пунктов.

Направление потока данных

Что инициирует обновления источника

Вне зависимости от того, каких элементы привязываются и какой источник

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

показанной на следующем рисунке:

Как показано в приведенном выше рисунке, связывание данных является по

существу мостом между целью привязки и источником привязки. На рисунке

представлены следующие основные концепции связывания данных WPF:

Обычно каждая привязка имеет четыре компонента: объект цели

привязки, свойство цели, источник привязки и путь к значению

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

содержимое TextBox со свойством Имя объекта Сотрудник, объектом

цели являетсяTextBox, свойством цели является свойство Text,

используемым значением является Имя, а объектом источника является

объект Сотрудник.

Свойством цели должно быть свойство зависимостей. Большинство

свойств UIElement является свойствами зависимостей, а большинство

свойств зависимостей, за исключением свойств, доступных только для

чтения, по умолчанию поддерживает связывание данных. (Свойства

зависимости можно определить только через типы DependencyObject, а

все элементы UIElement производятся от DependencyObject).

Хотя на рисунке это не показано, однако следует отметить, что объект

источника привязки не обязательно должен быть пользовательским

объектом CLR. Привязка данных WPF поддерживает данные в форме

объектов CLR и XML. Например, источником привязки может

быть UIElement, любой объект списка, объект CLR, связанный с

данными ADO.NET или веб-службами, или узел XmlNode, содержащий

данные XML.Дополнительные сведения см. в разделе Общие сведения

об источниках привязки.

Page 5: General Facts About Binding

В процессе чтения других разделов software development kit (SDK) важно

помнить, что при связывании цель привязки привязывается к источнику

привязки. Например, при отображении некоторых базовых данных XML

в ListBox с использованием привязки данных, ListBox привязывается к

данным XML.

Чтобы установить привязку, используйте объект Binding. В остальной части

этого раздела обсуждаются многие понятия, связанные с некоторыми

свойствами и использованием объекта Binding.

Направление потока данных

Как упоминалось ранее и как показывает стрелка на приведенном выше

рисунке, поток данных связывания может идти от цели привязки к источнику

привязки (например, исходное значение изменяется, когда пользователь

изменяет значение TextBox) и/или от источника привязки к цели привязки

(например, содержимое TextBox обновляется при изменениях в источнике

привязки), если источник привязки предоставляет соответствующие

уведомления.

Возможно, требуется, чтобы в приложении пользователи могли изменить

данные и передать их обратно объекту источника. Или может потребоваться

не предоставлять пользователям возможности обновления источника

данных. Это можно регулировать с помощью

свойства Mode объекта Binding. На следующем рисунке показаны различные

типы потоков данных:

Связывание OneWay приводит к изменениям свойства источника для

автоматического обновления свойства цели, но изменения свойства цели

не передаются обратно к свойству источника. Этот тип привязки

подходит, если привязка элемента управления неявно доступна только

для чтения.Например, можно привязаться к источнику, такому как

биржевые сводки, или, возможно, свойство цели не имеет интерфейса

для внесения изменений, например цвета фона привязанной к данным

таблицы. Если отсутствует необходимость отслеживать изменения

свойства цели, можно использовать режим привязки OneWay, при

котором удастся избежать издержек режима привязки TwoWay.

Тип связывания TwoWay вызывает изменения либо свойства цели, либо

свойства источника для автоматического обновления другого. Этот тип

привязки подходит для изменяемых форм или других полностью

интерактивных скриптов UI. Большинство свойств являются свойствами

по умолчанию для связывания OneWay, но некоторые свойства

зависимостей (обычно свойства изменяемых пользователями элементов

управления, такие как свойство Text элемента TextBox и

Page 6: General Facts About Binding

свойство IsChecked элемента CheckBox) являются свойствами по

умолчанию для связывания TwoWay.Определить программный

способом, связано ли по умолчанию свойство зависимостей

односторонним или двусторонним способом, можно, получив

метаданные свойства с помощью GetMetadata, а затем проверив

логическое значение свойства BindsTwoWayByDefault.

Связывание OneWayToSource является обратным к

связыванию OneWay; оно обновляет свойство источника при изменении

свойства цели. Одним примером скрипта является пересчет значения

цели из UI.

На рисунке не показана привязка OneTime, которая вызывает

инициализацию свойства цели свойством источника, но последующие

изменения при этом не распространяются. This means that if the data

context undergoes a change or the object in the data context changes, then the

change is not reflected in the target property. Этот тип привязки подходит

при использовании данных, если для этого подходит моментальный

снимок текущего состояния, или данные являются статическими. Этот

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

инициализировать целевое свойство с некоторым значением из

исходного свойства, и контекст данных не известен заранее. По

существу, это является простой формой связывания OneWay, которая

обеспечивает лучшую производительность в случаях, когда значение

цели не изменяется.

Обратите внимание, что для обнаружения изменений в источнике

(применимо для связывания OneWay и TwoWay), источник должен

реализовывать подходящий механизм уведомления об изменении свойства,

такой как INotifyPropertyChanged. Пример реализации

класса INotifyPropertyChanged см. в разделе Практическое руководство.

Реализация уведомления об изменении свойства.

На странице свойства Mode содержатся дополнительные сведения о режимах

привязки и пример того, как указать направление привязки.

Что инициирует обновления источника

Привязки типовTwoWay и OneWayToSource отслеживают изменения

свойства цели и передают их обратно к источнику. Это называется

обновлением источника. Например, можно изменять текст элемента TextBox

для изменения базового значение источника. Как описано в последнем

разделе, направление потока данных определяется значением свойства

привязки Mode.

Однако обновляется ли значение источника при изменении текста или после

завершения изменения текста и отвода указателя мыши от элемента

TextBox?Свойство UpdateSourceTrigger привязки определяет, что инициирует

обновление источника. Точки стрелок вправо на следующем рисунке

показывают роль свойства UpdateSourceTrigger:

Page 7: General Facts About Binding

Если значение элемента UpdateSourceTrigger равно PropertyChanged,

значение, на которое указывает правая стрелка

привязок TwoWay илиOneWayToSource, обновляется сразу же после

изменения свойства цели. Однако если

значение UpdateSourceTrigger равно LostFocus, значение обновляется только

тогда, когда свойство цели теряет фокус.

Аналогично свойству Mode, различные свойства зависимостей имеют

различные значения по умолчанию для UpdateSourceTrigger. Значением по

умолчанию для большинства свойств зависимостей

является PropertyChanged, в то время как свойствоText по умолчанию имеет

значение LostFocus. Это означает, что обновления цели обычно происходят

при изменении свойства цели, что подходит для CheckBox и других простых

элементов управления.Однако для текстовых полей обновления после

каждого нажатия клавиши уменьшают производительность и не дают

пользователю обычной возможности удаления предыдущего символа и

исправления ошибок ввода до того, как новое значение будет

зафиксировано. Именно поэтому свойствоText по умолчанию имеет

значение LostFocus вместо PropertyChanged.

Сведения о том, как найти значение по

умолчанию UpdateSourceTrigger свойства зависимостей, см. на странице

свойства UpdateSourceTrigger.

В следующей таблице представлены примеры скриптов для каждого

значения UpdateSourceTrigger, использующие TextBox как пример:

Значение

UpdateSourceTrigger

Когда обновляется

значение источника

Пример скрипта для TextBox

LostFocus (значение

по умолчанию

для TextBox.Text)

Возникает при потере

фокуса элементом

управления TextBox.

TextBox, который связан с логикой

проверки (см. раздел "Проверка

данных")

PropertyChanged При вводе в TextBox Элемент управления TextBox в окне

чата

Explicit Когда приложение

вызываетUpdateSource

Элемент управления TextBox в

редактируемой форме (обновляет

значения источника только при

нажатии пользователем кнопки

отправки)

Page 8: General Facts About Binding

Пример см. в разделе Практическое руководство. Управление обновлением

источника из поля TextBox.

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

Этот подраздел состоит из следующих пунктов.

Указание источника привязки

Указание пути к значению

Связывание и выражение привязки

Подводя итог некоторым основным понятиям, описанным в предыдущих

разделах, следует сказать, что связывание устанавливается с помощью

объектаBinding и каждая привязка обычно состоит из четырех компонентов:

цель привязки, свойство цели, источник привязки и путь к используемому

значению источника. Этот раздел описывает установку привязки.

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

является класс с именем MyData, определенный в пространстве

именSDKSample. В качестве демонстрационного примера

класс MyData имеет строковое свойство ColorName, установленное в

значение "Красный". Таким образом, этот пример создает кнопку с красным

фоном.

XAML

<DockPanel

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:c="clr-namespace:SDKSample">

<DockPanel.Resources>

<c:MyData x:Key="myDataSource"/>

</DockPanel.Resources>

<DockPanel.DataContext>

<Binding Source="{StaticResource myDataSource}"/>

</DockPanel.DataContext>

<Button Background="{Binding Path=ColorName}"

Width="150" Height="30">I am bound to be RED!</Button>

</DockPanel>

Дополнительные сведения о синтаксисе объявления привязки и примеры

настройки привязки в коде см. в разделе Общие сведения об объявлении

привязок.

Если применить этот пример к основной диаграмме, полученное

изображение будет выглядеть следующим образом. Это привязка OneWay,

так как свойство Background по умолчанию поддерживает привязку OneWay.

Page 9: General Facts About Binding

Может вызвать удивление, почему это работает, несмотря на то, что

свойство ColorName — строковое, в то время как

свойство Background является свойством типа Brush. Это происходит в

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

разделе Преобразование данных.

Указание источника привязки

Обратите внимание, что в предыдущем примере источник привязки

определялся установкой свойства DataContext на

элементе DockPanel. Затем Buttonнаследует

значение DataContext от DockPanel, являющегося его родительским

элементом. Повторим, что объект источника привязки является одним из

четырех необходимых компонентов привязки. Таким образом, без указания

объекта источника привязки эта привязка не имела бы смысла.

Есть несколько способов для указания объекта источника привязки. С

помощью свойства DataContext родительского элемента удобно привязывать

несколько свойств к одному источнику. Однако иногда удобнее указывать

источник привязки в отдельных объявлениях привязки. В предыдущем

примере вместо использования свойства DataContext можно указать источник

привязки, установив свойство Source непосредственно в объявлении

привязки кнопки, как показано в следующем примере:

XAML

<DockPanel.Resources>

<c:MyData x:Key="myDataSource"/>

</DockPanel.Resources>

<Button Width="150" Height="30"

Background="{Binding Source={StaticResource myDataSource},

Path=ColorName}">I am bound to be RED!</Button>

Кроме установки свойства DataContext непосредственно в элементе,

наследования значения DataContext от предка (как, например, кнопки в

первом примере) и явного указания источника привязки установкой

свойства Source на Binding (например, кнопки в последнем примере), можно

также использовать свойство ElementName или свойство RelativeSource для

указания источника привязки. Свойство ElementName полезно при

связывании с другими элементами приложения, например при использовании

ползунка для настройки ширины

кнопки. Свойство RelativeSource используется при установке связывания

Page 10: General Facts About Binding

в ControlTemplate или Style. Дополнительные сведения см. в

разделе Практическое руководство. Указание источника привязки.

Указание пути к значению

Если источник привязки является объектом, используйте свойство Path для

указания значения, используемого для привязки. При связывании данных

XML используйте свойство XPath для указания значения. В некоторых

случаях удобно применить свойство Path, даже если это данные

XML. Например, если требуется получить доступ к свойству "Имя"

возвращаемого XmlNode (в результате выполнения запроса XPath), следует

использовать свойство Path в дополнении к свойству XPath.

Сведения о синтаксисе и примеры см. в описании свойств Path и XPath.

Обратите внимание, что хотя мы и подчеркнули, что путь Path к

используемому значению является одним из четырех необходимых

компонентов связывания, в скриптах, которые требуется привязать к всему

объекту, используемое значение должно быть таким же, как и у объекта

источника привязки. В этих случаях оно применяется без

указания Path. Рассмотрим следующий пример:

XAML

<ListBox ItemsSource="{Binding}"

IsSynchronizedWithCurrentItem="true"/>

В приведенном выше примере используется синтаксис пустой привязки:

{Привязка}. В этом случае ListBox наследует DataContext от родительского

элемента DockPanel (не показан в этом примере). Если путь не указан, по

умолчанию производится привязка к всему объекту. Другими словами, в

этом примере путь не был указан, так как мы выполнили привязку

свойства ItemsSource ко всему объекту. (Подробное обсуждение см. в

разделе Привязка к коллекции.)

Кроме привязки к коллекции, этот скрипт полезен также для возможности

привязки ко всему объекту, а не только к одному свойству

объекта. Например, если объект источника является объектом строкового

типа, и всего лишь нужна привязка к самой строке. Другим

распространенным скриптом является необходимость привязки элемента к

объекту с несколькими свойствами.

Обратите внимание, что вам, возможно, потребуется применить

пользовательскую логику, чтобы данные были применимы к вашему

привязанному свойству цели. Пользовательская логика может быть

представлена в виде пользовательского преобразователя (если не существует

преобразования типа по умолчанию). Сведения о преобразователях см. в

разделе Преобразование данных.

Связывание и выражение привязки

До разъяснения других функций и использования привязки данных, было бы

полезно рассказать о классе BindingExpression. Как было показано в

Page 11: General Facts About Binding

предыдущих разделах, класс Binding является классом высокого уровня для

объявления привязки; класс Binding предоставляет множество свойств,

которые позволяют указать характеристики привязки. Связанный

класс, BindingExpression, является базовым объектом, поддерживающим

связь между источником и целью. Привязка содержит всю информацию,

которая может использоваться совместно в нескольких выражениях

привязки.BindingExpression представляет собой экземпляр выражения,

который не может быть общим и который содержит все сведения об

экземпляре Binding.

Например, рассмотрим следующую ситуацию, когда myDataObject является

экземпляром классаMyData, myBinding является источником объекта Binding,

а классMyData представляет собой определенный класс, содержащий

строковое свойство MyDataProperty. В этом примере привязывается

текстовое содержимое MyText, экземпляр класса TextBlock,

к MyDataProperty.

//make a new source

MyData myDataObject = new MyData(DateTime.Now);

Binding myBinding = new Binding("MyDataProperty");

myBinding.Source = myDataObject;

myText.SetBinding(TextBlock.TextProperty, myBinding);

Можно использовать один и тот же объект myBinding для создания других

привязок. Например, можно использовать объект myBinding для привязки

текстового содержимого элемента флажка к MyDataProperty. В этом

сценарии будут два экземпляра BindingExpression, совместно использующих

объектmyBinding.

Объект BindingExpression может быть получен с помощью возвращаемого

значения метода GetBindingExpression для объекта с привязкой к данным. В

следующих разделах демонстрируются некоторые примеры использования

класса BindingExpression:

Практическое руководство. Получение объекта привязки из свойства

целевого объекта привязки

Практическое руководство. Управление обновлением источника из поля

TextBox

Преобразование данных

В предыдущем примере кнопка красная, так как ее

свойство Background привязано к строковому свойству со значением

"Красный". Это работает, поскольку для типа Brush существует

преобразователь, который преобразует строковое значение в значение

типа Brush.

Если добавить эти сведения в рисунок из раздела Создание привязки, то

диаграмма будет выглядеть следующим образом:

Page 12: General Facts About Binding

Однако, что делать, если вместо свойства строкового типа объект источника

привязки имеет свойство Цвет типа Color? В этом случае для создания

привязки в первую очередь необходимо преобразовать значение

свойства Цвет во что-то, что примет свойство Background. Необходимо

создать пользовательский преобразователь, реализующий

интерфейс IValueConverter, как в следующем примере:

[ValueConversion(typeof(Color), typeof(SolidColorBrush))]

public class ColorBrushConverter : IValueConverter

{

public object Convert(object value, Type targetType, object parameter, System.

Globalization.CultureInfo culture)

{

Color color = (Color)value;

return new SolidColorBrush(color);

}

public object ConvertBack(object value, Type targetType, object parameter, Sys

tem.Globalization.CultureInfo culture)

{

return null;

}

}

Страница ссылки IValueConverter предоставляет дополнительные сведения.

Теперь пользовательский преобразователь используется вместо

преобразования по умолчанию, и наша диаграмма выглядит следующим

образом:

Таким образом, преобразования по умолчанию могут быть доступны

благодаря преобразователям типов, присутствующим в типе, к которому

производится привязка. Такое поведение будет зависеть от того, какие

преобразователи типов доступны в цели. Если существуют какие-то

сомнением, создайте свой собственный преобразователь.

Page 13: General Facts About Binding

Ниже приведены некоторые типовые сценарии, где имеет смысл реализация

преобразователя данных.

Данные должны отображаться по-разному, в зависимости от

региональных стандартов. Например, можно реализовать

преобразователь валюты или преобразователь даты/времени в календаре

на основе значений или стандартов, используемых в определенных

региональных стандартах.

Используемые данные не обязательно предназначены для изменения

текстового значения свойства, а предназначены для изменения

некоторых других значений, например, источника изображения, цвета

или стиля отображаемого текста. Преобразователи могут

использоваться в данном экземпляре для преобразования привязки

неподходящего свойства, например, привязки текстового поля к

свойству Background ячейки таблицы.

К одним и тем же данным может быть привязано более одного элемента

управления или несколько свойств элемента управления. В этом случае

основная привязка может просто отображать текст, тогда как другие

привязки обрабатывают специфичные проблемы отображения, но они

по-прежнему используют одну и ту же привязку в качестве источника

информации.

Пока еще мы не рассматривали MultiBinding, где свойство цели имеет

коллекцию привязок. В случае MultiBinding следует использовать

пользовательский IMultiValueConverter для получения окончательного

значения из значений привязок. Например, цвет может быть вычислен

из соотношения красного, синего и зеленого значений, которые могут

быть значениями одних и тех же или разных объектов источника

привязки.Примеры и другие сведения содержатся на странице

класса MultiBinding.

Привязка к коллекциям

Этот подраздел состоит из следующих пунктов.

Способы реализации коллекций

Представления коллекций

Объект источника привязки может рассматриваться как отдельный объект,

свойства которого содержат данные, или как коллекцию данных

полиморфных объектов, часто группируемых вместе (например, в результате

запроса к базе данных). Пока еще мы обсуждали привязку только к одному

объекту, однако привязка к коллекции данных является распространенным

скриптом. Например, обычным сценарием является

использованиеItemsControlнапример ListBox, ListView, или TreeViewдля

отображения данных коллекции, как показано в приложении в что такое

привязка данных?раздел.

К счастью, наша основная диаграмма по-прежнему применима. Если

привязать ItemsControl к коллекции, диаграмма будет выглядеть следующим

образом:

Page 14: General Facts About Binding

Как показано на этой диаграмме, выполнить привязку ItemsControl к объекту

коллекции можно с помощью

свойства ItemsSource. Свойство ItemsSourceможно представить как

содержимое ItemsControl. Обратите внимание, что привязка является

привязкой типа OneWay, поскольку свойство ItemsSource по умолчанию

поддерживает привязку OneWay.

Способы реализации коллекций

Пользователь может выполнить перечисление элементов любой коллекции,

реализующей интерфейс IEnumerable. Однако чтобы настроить динамические

привязки таким образом, чтобы вставки и удаления элементов в коллекции

автоматически обновляли UI, в коллекции должен быть реализован

интерфейсINotifyCollectionChanged. Этот интерфейс предоставляет событие,

которое должно быть инициировано при изменении базовой коллекции.

WPF предоставляет класс ObservableCollection<T>, который является

встроенной реализацией коллекции данных, предоставляющей

интерфейсINotifyCollectionChanged. Обратите внимание, что для полной

поддержки передачи значений данных от объектов источника в цели каждый

объект в коллекции, который поддерживает свойства связывания, должен

также реализовывать интерфейс INotifyPropertyChanged. Дополнительные

сведения см. в разделе Общие сведения об источниках привязки.

До реализации собственной коллекции рассмотрите возможность

использования класса ObservableCollection<T> или одного из существующих

классов коллекций, таких как List<T>, Collection<T> и BindingList<T> (среди

многих прочих). Если имеется расширенный скрипт и требуется реализовать

свою собственную коллекцию, следует рассмотреть возможность

использования IList, которая предоставляет коллекцию объектов, к которым

можно по отдельности обращаться по индексу и следовательно, максимально

быстро.

Представления коллекций

Так как ItemsControl связан с коллекцией данных, существует возможность

сортировать, фильтровать или группировать данные. Для этого используется

представления коллекций, которые являются классами, реализующими

интерфейс ICollectionView.

Этот подраздел состоит из следующих пунктов.

Понятие о представлениях коллекций

Создание представления

Сортировка

Фильтрация

Группировка

Page 15: General Facts About Binding

Указатели на текущий элемент

Скрипт привязки "основной/подробности"

Понятие о представлениях коллекций

Представление коллекции — это слой, расположенный в верхней части

связанной исходной коллекции, с помощью которого можно перемещаться

по исходной коллекции и просматривать ее содержимое на основе запросов

сортировки, фильтрации и группировки, не изменяя саму коллекцию. В

представлении коллекции также поддерживается указатель на текущий

элемент коллекции. Если в исходной коллекции реализован

интерфейсINotifyCollectionChanged, изменения, инициированные

событием CollectionChanged, передаются представлениям.

Поскольку представления не изменяют базовые исходные коллекции, каждая

исходная коллекция может иметь несколько связанных с ней

представлений.Например, можно иметь коллекцию объектов Задача. С

помощью представлений можно отображать одни и те же данные

различными способами.Например, в левой части страницы можно

отображать задачи, отсортированные по приоритету, а справа —

сгруппированные по областям.

Создание представления

Одним из способов создания и использования представления является

непосредственное создание объекта представления, и затем использование

его в качестве источника привязки. Например, рассмотрим

в приложения http://go.microsoft.com/fwlink/?LinkID=163703 что такое

привязка данных? раздел.Приложение реализовано таким образом,

что ListBox привязывается к представлению коллекции данных, а не к

коллекции данных напрямую. Следующий пример извлечен из

приложения Пример привязки данных. Класс CollectionViewSource является

прокси Extensible Application Markup Language (XAML) для класса,

производного от CollectionView. В этом отдельном примере

источник Source представления привязан к

коллекции AuctionItems (типаObservableCollection<T>) объекта текущего

приложения.

XAML

<Window.Resources>

...

<CollectionViewSource

Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems

}"

x:Key="listingDataView" />

...

</Window.Resources>

Page 16: General Facts About Binding

Ресурс listingDataView затем служит источником привязки для элементов в

приложении, таких как ListBox:

XAML

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"

ItemsSource="{Binding Source={StaticResource listingDataView}}">

...

</ListBox>

Чтобы создать другое представление для той же коллекции, можно создать

другой экземпляр CollectionViewSource и присвоить ему другое имя x:Key.

В приведенной ниже таблице показано, какие типы данных представления

созданы в качестве представления коллекции по умолчанию либо

объектомCollectionViewSource на основе типа исходной коллекции.

Тип исходной

коллекции

Тип представления коллекции Примечания

IEnumerable Внутренний тип, основанный

на CollectionView

Не удается

сгруппировать

элементы.

IList ListCollectionView Самый быстрый.

IBindingList BindingListCollectionView

Использование представления по умолчанию

Один из способов создания и использования представления коллекции

заключается в указании представления коллекции в качестве источника

привязки.WPF также создает представление коллекции по умолчанию для

каждой коллекции, используемой в качестве источника привязки. Если

выполнить привязку непосредственно к коллекции, WPF выполнит привязку

к представлению коллекции по умолчанию. Обратите внимание, что данное

представление по умолчанию совместно используется всеми привязками к

одной и той же коллекции, поэтому изменения, внесенные в представление

по умолчанию одним привязанным элементом управления либо кодом

(например сортировка или изменение указателя на текущий элемент, что

будет рассмотрено ниже), распространяются на все привязки к одной

коллекции.

Чтобы получить представление по умолчанию, используйте

метод GetDefaultView. Пример см. в разделе Практическое руководство.

Получение представления по умолчанию для коллекции данных.

Использование представлений коллекций с таблицами данных

ADO.NET

Для повышения производительности представления коллекций для объектов

ADO.NET DataTable и DataView делегируют функции сортировки и

фильтрации объекту DataView. При этом функции сортировки и фильтрации

Page 17: General Facts About Binding

совместно используются всеми представлениями коллекции для источника

данных. Чтобы включить возможность независимой сортировки и

фильтрации для каждого представления коллекции, инициализируйте каждое

представление коллекции с использованием собственного объекта DataView.

Сортировка

Как уже отмечалось ранее, представления могут применять сортировку для

коллекции. Так как данные находятся в базовой коллекции, они могут иметь

или не иметь некий порядок следования. Представление коллекции позволяет

установить порядок или изменить порядок, используемый по умолчанию, на

основе введенных признаков сравнения. Так как это представление данных

на стороне клиента, распространенным скриптом является сортировка

пользователем столбцов табличных данных по значениям, содержащимся в

столбце. С использованием представлений, управляемая пользователем

сортировка может применяться еще раз без необходимости внесения

изменений в основную коллекцию или создания повторного запроса к

содержимому коллекции. Пример см. в разделе Практическое руководство.

Сортировка столбцов GridView при нажатии на заголовок.

В следующем примере показан алгоритм сортировки «Сортировать по

категории» и «дата» CheckBoxприложения UIв что такое привязка

данных? раздел:

private void AddSorting(object sender, RoutedEventArgs args)

{

// This sorts the items first by Category and within each Category,

// by StartDate. Notice that because Category is an enumeration,

// the order of the items is the same as in the enumeration declaration

listingDataView.SortDescriptions.Add(

new SortDescription("Category", ListSortDirection.Ascending));

listingDataView.SortDescriptions.Add(

new SortDescription("StartDate", ListSortDirection.Ascending));

}

Фильтрация

Представления могут применять к коллекции фильтр. Это означает, что

несмотря на то, что элемент может существовать в коллекции, его

конкретное представление предназначено для отображения только

некоторого подмножества полной коллекции. Возможна фильтрация по

условию в данных.Например, как выполняется приложением в что такое

привязка данных? раздела "Показывать только bargains" CheckBoxсодержит

логику для фильтрации элементов, стоимость $ 25 или более. Следующий

код выполняется для установки фильтра ShowOnlyBargainsFilter в качестве

обработчика событий Filterпри выборе этого CheckBox:

Page 18: General Facts About Binding

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

Обработчик событий ShowOnlyBargainsFilter реализуется следующим

образом:

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)

{

AuctionItem product = e.Item as AuctionItem;

if (product != null)

{

// Filter out products with price 25 or above

if (product.CurrentPrice < 25)

{

e.Accepted = true;

}

else

{

e.Accepted = false;

}

}

}

Если используется один из классов CollectionView непосредственно

вместо CollectionViewSource, следует использовать свойство Filter для

указания обратного вызова. Пример см. в разделе Практическое руководство.

Фильтрация данных в представлении.

Группировка

За исключением внутреннего класса, предназначенного для просмотра

коллекции IEnumerable, все представления коллекций поддерживают

функцию группировки, которая позволяет пользователю логически разбить

коллекцию в представлении коллекции на группы. Группы могут быть

явными, если пользователь предоставляет список групп, или неявными, если

эти группы создаются динамически в зависимости от данных.

В следующем примере показана логика флажка CheckBox "Группировка по

категориям"

// This groups the items in the view by the property "Category"

PropertyGroupDescription groupDescription = new PropertyGroupDescription();

groupDescription.PropertyName = "Category";

listingDataView.GroupDescriptions.Add(groupDescription);

Другой пример группировки см. в разделе Практическое руководство.

Группировка элементов в объекте ListView, реализующем GridView.

Page 19: General Facts About Binding

Указатели на текущий элемент

В представлениях также присутствует понятие текущего

элемента. Существует возможность перемещаться по объектам в

представлении коллекции. При переходе перемещается указатель элемента,

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

коллекции. Пример см. в разделеПрактическое руководство. Перемещение по

объектам в Data CollectionView.

Поскольку WPF выполняет привязку к коллекции только через

представление коллекции (либо указанное пользователем, либо

представление коллекции по умолчанию), для всех привязок к коллекциям

имеется указатель на текущий элемент. При привязке к представлению знак

косой черты ("/") в значенииPath указывает на текущий элемент

представления. В приведенном ниже примере контекст данных является

представлением коллекции. В первой строке выполняется привязка к

коллекции. Во второй строке выполняется привязка к текущему элементу

коллекции. В третьей строке выполняется привязка к

свойству Description текущего элемента коллекции.

XAML

<Button Content="{Binding }" />

<Button Content="{Binding Path=/}" />

<Button Content="{Binding Path=/Description}" />

Косую черту и синтаксис свойства также можно комбинировать для

обработки иерархии коллекций. В приведенном ниже примере выполняется

привязка к текущему элементу коллекции Offices, которая является

свойством текущего элемента исходной коллекции.

XAML

<Button Content="{Binding /Offices/}" />

На указатель текущего элемента влияют примененные к коллекции операции

сортировки и фильтрации. При сортировке указатель текущего элемента

устанавливается на последний выбранный элемент, однако представление

коллекции перестраивается относительно его. (Возможно, до этого

выбранный элемент был в начале списка, но теперь выбранный элемент

может оказаться где-нибудь в середине). При фильтрации выбранный

элемент сохраняется, если данный выбор остается в представлении после

фильтрации. В противном случае указатель текущего элемента

устанавливается на первый элемент отфильтрованного представления

коллекции.

Скрипт привязки "основной/подробности"

Понятие текущего элемента применимо не только для перемещения

элементов в коллекции, но также для скрипта привязки

"основной/подробности".Рассмотрим приложение UIв что такое привязка

данных?еще раз раздел. В этом приложении выделение в ListBox определяет

содержимое, показанное вContentControl. При выборе

элемента ListBoxContentControl отображает подробные сведения о

выбранном элементе, что позволяет поместить выделение другим способом.

Page 20: General Facts About Binding

Для выполнения скрипта необходимо наличие двух или более элементов

управления, привязанных к одному и тому же представлению. В следующем

примере из http://go.microsoft.com/fwlink/?LinkID=163703 показана

разметка ListBoxи ContentControlсодержатся в приложении UIв что такое

связывание данных? раздел:

XAML

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"

ItemsSource="{Binding Source={StaticResource listingDataView}}">

...

</ListBox>

...

<ContentControl Name="Detail" Grid.Row="3" Grid.ColumnSpan="3"

Content="{Binding Source={StaticResource listingDataView}}"

ContentTemplate="{StaticResource detailsProductListingTemplate}"

Margin="9,0,0,0"/>

Обратите внимание, что оба элемента управления привязаны к одному

источнику, статическому ресурсу listingDataView (просмотреть определение

этого ресурса можно в разделе Создание представления). Это работает, так

как если объект одноэлементного множества (в данном

случае ContentControl) связан с представлением коллекции, он автоматически

привязывается к CurrentItem представления. Обратите внимание, что

объекты CollectionViewSourceавтоматически синхронизуют значения

денежного формата и выделение. Если элемент управления списка не

привязан к объекту CollectionViewSource, как в этом примере, для

корректной работы необходимо задать его

свойству IsSynchronizedWithCurrentItem значение true.

Другие примеры содержатся в разделах Практическое руководство.

Выполнение привязки к коллекции и вывод сведений в зависимости от

выделенного элемента и Практическое руководство. Использование шаблона

"основной-подчиненный" с иерархическими данными.

Можно заметить, что в приведенном выше примере используется

шаблон. Фактически данные не будут отображаться выбранным способом без

использования шаблонов (один явно используется элементом ContentControl,

а другой — неявно элементом ListBox). К шаблонам данных мы перейдем в

следующем разделе.

Шаблоны данных

Без использования шаблонов данных, наше приложение UIв что такое

привязка данных? раздел будет выглядеть следующим образом:

Page 21: General Facts About Binding

Как показано в примере из предыдущего раздела, оба элемента

управления ListBox и ContentControl привязываются ко всему объекту

коллекции (а точнее, к представлению объекта коллекции)

элементов AuctionItem. При отсутствии особых инструкций по способу

отображения сбора данных элемент управления ListBox отображает

строковое представление каждого объекта в базовой коллекции, а элемент

управления ContentControl отображает строковое представление

привязанного к ней объекта.

Чтобы устранить эту проблему, приложение задает

шаблоны DataTemplate. Как показано в примере из предыдущего раздела,

элемент управленияContentControl явно использует

шаблон detailsProductListingTemplateDataTemplate. Элемент

управления ListBox неявно использует следующийDataTemplate для

отображении объектов AuctionItem в коллекции:

XAML

<DataTemplate DataType="{x:Type src:AuctionItem}">

<Border BorderThickness="1" BorderBrush="Gray"

Padding="7" Name="border" Margin="3" Width="500">

<Grid>

<Grid.RowDefinitions>

<RowDefinition/>

<RowDefinition/>

<RowDefinition/>

<RowDefinition/>

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="20"/>

Page 22: General Facts About Binding

<ColumnDefinition Width="86"/>

<ColumnDefinition Width="*"/>

</Grid.ColumnDefinitions>

<Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"

Fill="Yellow" Stroke="Black" StrokeThickness="1"

StrokeLineJoin="Round" Width="20" Height="20"

Stretch="Fill"

Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"

Visibility="Hidden" Name="star"/>

<TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"

Name="descriptionTitle"

Style="{StaticResource smallTitleStyle}">Description:</TextBlock

>

<TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column

="2"

Text="{Binding Path=Description}"

Style="{StaticResource textStyleTextBlock}"/>

<TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"

Name="currentPriceTitle"

Style="{StaticResource smallTitleStyle}">Current Price:</TextBloc

k>

<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">

<TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>

<TextBlock Name="CurrentPriceDTDataType"

Text="{Binding Path=CurrentPrice}"

Style="{StaticResource textStyleTextBlock}"/>

</StackPanel>

</Grid>

</Border>

<DataTemplate.Triggers>

<DataTrigger Binding="{Binding Path=SpecialFeatures}">

<DataTrigger.Value>

<src:SpecialFeatures>Color</src:SpecialFeatures>

</DataTrigger.Value>

<DataTrigger.Setters>

<Setter Property="BorderBrush" Value="DodgerBlue" TargetName="bord

er" />

<Setter Property="Foreground" Value="Navy" TargetName="descriptionTi

tle" />

<Setter Property="Foreground" Value="Navy" TargetName="currentPrice

Title" />

<Setter Property="BorderThickness" Value="3" TargetName="border" />

Page 23: General Facts About Binding

<Setter Property="Padding" Value="5" TargetName="border" />

</DataTrigger.Setters>

</DataTrigger>

<DataTrigger Binding="{Binding Path=SpecialFeatures}">

<DataTrigger.Value>

<src:SpecialFeatures>Highlight</src:SpecialFeatures>

</DataTrigger.Value>

<Setter Property="BorderBrush" Value="Orange" TargetName="border" /

>

<Setter Property="Foreground" Value="Navy" TargetName="descriptionTi

tle" />

<Setter Property="Foreground" Value="Navy" TargetName="currentPrice

Title" />

<Setter Property="Visibility" Value="Visible" TargetName="star" />

<Setter Property="BorderThickness" Value="3" TargetName="border" />

<Setter Property="Padding" Value="5" TargetName="border" />

</DataTrigger>

</DataTemplate.Triggers>

</DataTemplate>

С помощью этих двух DataTemplates, итоговый интерфейс пользователя

будет показано на что такое привязка данных? раздел. Как можно увидеть из

этого моментального снимка, в дополнение к тому, что DataTemplate дают

возможность располагать данные в элементах управления, они позволяют

определять подходящие визуальные элементы для данных. Например,

элементы DataTrigger используются в указанном выше DataTemplate, так что

элементыAuctionItem со значением SpecialFeatures для HighLight будут

отображаться с оранжевой границей и звездочкой.

Дополнительные сведения о шаблонах данных см. в разделе Общие сведения

о шаблонах данных.

Проверка данных

Этот подраздел состоит из следующих пунктов.

Связь проверочных правил и привязки

Предоставление визуального отклика

Процесс проверки

Для большинства приложений, принимающих входные данные от

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

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

типе, диапазоне, формате или других требованиях конкретного

приложения. В этом разделе рассматривается, как проверка данных работает

в WPF.

Связь проверочных правил и привязки

Page 24: General Facts About Binding

Модель привязки данных WPF позволяет связать свойство ValidationRules с

объектом Binding. Например, в следующем примере выполняется привязка

элемента управления TextBox к свойству с именем StartPrice и добавление

объекта ExceptionValidationRule к свойству Binding.ValidationRules.

XAML

<TextBox Name="StartPriceEntryForm" Grid.Row="2" Grid.Column="1"

Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">

<TextBox.Text>

<Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">

<Binding.ValidationRules>

<ExceptionValidationRule />

</Binding.ValidationRules>

</Binding>

</TextBox.Text>

</TextBox>

Объект ValidationRule выполняет проверку допустимости значения

свойства. В WPF имеется два следующих типа встроенных

объектов ValidationRule:

Объект ExceptionValidationRule проверяет исключения, возникшие во

время обновления привязанного исходного свойства. В предыдущем

примере StartPrice имеет тип integer. Когда пользователь вводит

значение, которое невозможно преобразовать в целое число, создается

исключение, приводящее к тому, что привязка будет помечена как

недопустимая. Чтобы явно установить ExceptionValidationRule, можно

также задать для свойства ValidatesOnExceptions значение true в

объекте Binding или MultiBinding.

Объект DataErrorValidationRule выполняет проверку ошибок объектов,

реализующих интерфейс IDataErrorInfo. Пример использования этого

правила проверки см. в разделе DataErrorValidationRule. Чтобы явно

установить DataErrorValidationRule, можно также задать для

свойстваValidatesOnDataErrors значение true в

объекте Binding или MultiBinding.

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

производный от класса ValidationRule, и реализовав метод Validate. В

следующем примере показано правило, используется Добавления списка

продукции "Дата начала" TextBoxиз что такое связывание данных? раздел:

class FutureDateRule : ValidationRule

{

public override ValidationResult Validate(object value, CultureInfo cultureInfo)

{

DateTime date;

try

Page 25: General Facts About Binding

{

date = DateTime.Parse(value.ToString());

}

catch (FormatException)

{

return new ValidationResult(false, "Value is not a valid date.");

}

if (DateTime.Now.Date > date)

{

return new ValidationResult(false, "Please enter a date in the future.");

}

else

{

return ValidationResult.ValidResult;

}

}

}

StartDateEntryForm TextBox использует это правило FutureDateRule, как

показано в следующем примере:

XAML

<TextBox Name="StartDateEntryForm" Grid.Row="3" Grid.Column="1"

Validation.ErrorTemplate="{StaticResource validationTemplate}"

Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">

<TextBox.Text>

<Binding Path="StartDate" UpdateSourceTrigger="PropertyChanged"

Converter="{StaticResource dateConverter}" >

<Binding.ValidationRules>

<src:FutureDateRule />

</Binding.ValidationRules>

</Binding>

</TextBox.Text>

</TextBox>

Обратите внимание, что поскольку

значение UpdateSourceTrigger является PropertyChanged, механизм привязки

обновляет значение источника при каждом нажатии клавиши, то есть он

также проверяет каждое правило в коллекции ValidationRules при каждом

нажатии клавиши. Это будет обсуждаться далее в разделе "Процесс

проверки".

Предоставление визуального отклика

Если пользователь вводит недопустимое значение, следует обеспечить

некоторый отклик приложения UI на ошибку. Одним из способов

Page 26: General Facts About Binding

обеспечения такого отклика является установка вложенного

свойства Validation.ErrorTemplate в пользовательский

шаблон ControlTemplate. Как показано в предыдущем

подразделе, StartDateEntryForm TextBox использует ErrorTemplate,

называемый шаблоном проверки. В следующем примере рассмотрено

определение элемента Шаблон проверки:

XAML

<ControlTemplate x:Key="validationTemplate">

<DockPanel>

<TextBlock Foreground="Red" FontSize="20">!</TextBlock>

<AdornedElementPlaceholder/>

</DockPanel>

</ControlTemplate>

Элемент AdornedElementPlaceholder указывает, куда будет помещен

выбранный элемент управления.

Кроме того, для вывода сообщения об ошибке можно

использовать ToolTip. И StartDateEntryForm,

и StartPriceEntryFormTextBox используют стильtextStyleTextBox, который

создает ToolTip, отображающий сообщение об ошибке. В следующем

примере рассмотрено определение элементаtextStyleTextBox: Вложенное

свойство Validation.HasError принимает значение true, если одна или

несколько привязок к свойствам связанного элемента вызвали ошибку.

XAML

<Style x:Key="textStyleTextBox" TargetType="TextBox">

<Setter Property="Foreground" Value="#333333" />

<Setter Property="MaxLength" Value="40" />

<Setter Property="Width" Value="392" />

<Style.Triggers>

<Trigger Property="Validation.HasError" Value="true">

<Setter Property="ToolTip"

Value="{Binding RelativeSource={RelativeSource Self},

Path=(Validation.Errors)[0].ErrorContent}"/>

</Trigger>

</Style.Triggers>

</Style>

При использовании пользовательских

шаблонов ErrorTemplate и ToolTipTextBox форма StartDateEntryForm при

ошибке проверки выглядит следующим образом:

Page 27: General Facts About Binding

Если привязка Binding имеет правила проверки, но не

указан ErrorTemplate на присоединенном элементе управления, для

уведомления пользователей об ошибке проверки по умолчанию будет

использоваться ErrorTemplate. ErrorTemplate по умолчанию — это шаблон

элемента управления, определяющий красную границу графического

уровня. С используемым по умолчанию ErrorTemplate и с ToolTip, элемент

UI формы StartPriceEntryForm TextBox при ошибке проверки выглядит

следующим образом:

Пример обеспечения логики проверки всех элементов управления в

диалоговом окне содержится в разделе "Пользовательские диалоговые окна"

вОбщие сведения о диалоговых окнах.

Процесс проверки

Проверка обычно выполняется, когда целевое значение передается свойству

источника привязки. Это выполняется для типов

привязки TwoWay иOneWayToSource. Таким образом, причина обновления

источника зависит от значения свойства UpdateSourceTrigger, как описано в

разделе Что инициирует обновления источника.

Ниже описан процесс проверки. Обратите внимание, что при возникновении

ошибки проверки или ошибки другого типа на любом этапе данного

процесса процесс будет прерван.

1. Обработчик привязки проверяет наличие настраиваемых

объектов ValidationRule, свойству ValidationStep которых присвоено

значениеRawProposedValue для данного типа привязки Binding; в этом

случае для каждого правила ValidationRule вызывается метод Validate,

пока одно из них не вернет ошибку или пока все они не будут

выполнены.

2. Обработчик привязки вызывает преобразователь, если таковой

существует.

3. При успешном завершении работы преобразователя обработчик

привязки проверяет наличие настраиваемых объектов ValidationRule,

свойствуValidationStep которых присвоено

значение ConvertedProposedValue для данного типа привязки Binding; в

этом случае для каждого правилаValidationRule,

свойству ValidationStep которого присвоено

значение ConvertedProposedValue, вызывается метод Validate, пока

одно из них не вернет ошибку или пока все они не будут выполнены.

4. Обработчик привязки присваивает значение исходному свойству.

5. Обработчик привязки проверяет наличие настраиваемых

объектов ValidationRule, свойству ValidationStep которых присвоено

значениеUpdatedValue для данного типа привязки Binding; в этом

Page 28: General Facts About Binding

случае для каждого правила ValidationRule,

свойству ValidationStep которого присвоено значение UpdatedValue,

вызывается метод Validate, пока одно из них не вернет ошибку или

пока все они не будут выполнены. Если

правилоDataErrorValidationRule связано с привязкой и его

свойству ValidationStep задано значение по умолчанию, UpdatedValue,

в этой точке производится проверка правила DataErrorValidationRule. В

этой же точке проверяются привязки, в которых для

свойства ValidatesOnDataErrorsустановлено значение true.

6. Обработчик привязки проверяет наличие настраиваемых

объектов ValidationRule, свойству ValidationStep которых присвоено

значениеCommittedValue для данного типа привязки Binding; в этом

случае для каждого правила ValidationRule,

свойству ValidationStep которого присвоено значение CommittedValue,

вызывается метод Validate, пока одно из них не вернет ошибку или

пока все они не будут выполнены.

Если правило ValidationRule не выполняется на любом этапе данного

процесса, обработчик привязки создает объект ValidationError и добавляет

его в коллекцию Validation.Errors связанного элемента. Перед запуском

обработчиком привязки объектов ValidationRule на любом этапе обработчик

привязки удаляет все объекты ValidationError, добавленные

во Validation.Errors вложенное свойство связанного элемента на

соответствующем этапе. Например, если правило ValidationRule,

свойству ValidationStep которого присвоено значение UpdatedValue, не

выполняется, то при следующей проверке обработчик привязки удалит

объект ValidationError непосредственно перед вызовом любого

правила ValidationRule, свойству ValidationStep которого присвоено

значение UpdatedValue.

Если свойство Validation.Errors не пусто, Validation.HasError вложенному

свойству элемента присваивается значение true. Кроме того, если

свойствуNotifyOnValidationError объекта Binding присвоено значение true,

обработчик привязки вызывает Validation.Error вложенное событие элемента.

Также обратите внимание, что при передаче допустимого значения в любом

направлении (от целевого объекта к источнику и от источника к целевому

объекту) очищается Validation.Errors вложенное свойство.

Если для привязки задано связанное с ней

правило ExceptionValidationRule или для ее

свойства ValidatesOnExceptions задано значение true и при задании

обработчиком привязки значения источника возникает исключение,

обработчик привязки проверяет наличие

фильтра UpdateSourceExceptionFilter.Имеется возможность использования

отклика UpdateSourceExceptionFilter для возможности создания

пользовательского обработчика исключений. Если фильтр

исключений UpdateSourceExceptionFilter для привязки Binding не указан,

Page 29: General Facts About Binding

обработчик привязки создает объект ValidationError с исключением и

добавляет его в коллекцию Validation.Errors связанного элемента.