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

Обновлен: Июль 2008

Привязка данных Windows Presentation Foundation (WPF) обеспечивает простой и согласованный способ представления данных и взаимодействия с ними в приложениях. Можно связывать элементы с данными из разнообразных источников данных в форме объектов среда CLR (common language runtime) и XML. Элементы управления ContentControl, например Button, элементы управления ItemsControl, например ListBox и ListView обладают встроенной возможностью включения гибких стилей для отдельных элементов данных и коллекций элементов данных. Представления сортировки, фильтрации и группировки могут быть организованы поверх данных.

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

В этом разделе сначала будут рассмотрены основные фундаментальные понятия связывания данных в WPF, а затем — использование класса Binding и других возможностей связывания данных.

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

  • Понятие о привязке к данным
  • Основные понятия связывания данных
  • Создание привязки
  • Преобразование данных
  • Привязка к коллекциям
  • Шаблоны данных
  • Проверка данных
  • Механизм отладки
  • Связанные разделы

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

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

Привязка к данным обычно используется для того, чтобы поместить сервер или локальную конфигурацию данных в формы или другие элементы управления Пользовательский интерфейс. В WPF эта концепция расширяется и уже включает привязку широкого диапазона свойств к различным источникам данных. В WPF, свойства зависимостей элементов могут быть привязаны к объектам CLR (включая объекты ADO.NET или объекты, связанные с веб-службами и веб-свойствами), и к данным XML.

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

Снимок экрана примера привязки данных

Выше показан интерфейс Пользовательский интерфейс приложения, который отображает список лотов аукциона. Приложение демонстрирует следующие возможности связывания данных:

  • Содержимое ListBox привязано к коллекции объектов AuctionItem. Объект AuctionItem имеет такие свойства как Description StartPrice StartDate, Category, SpecialFeatures и т.д.

  • Данные (объекты AuctionItem), отображаемые в ListBox, используются в шаблоне таким образом, что для каждого элемента показаны его описание и текущая цена. Это делается с помощью DataTemplate. Кроме того, внешний вид каждого элемента зависит от значенияSpecialFeatures отображаемого объекта AuctionItem. Если значением SpecialFeatures объекта AuctionItem является Color, элемент имеет синюю границу. Если значением является Highlight, элемент имеет оранжевые границы и помечается звездочкой. Раздел Создание шаблонов данных содержит сведения о создании шаблонов данных.

  • Пользователь может группировать, фильтровать или сортировать данные с помощью предоставленных элементов CheckBox. На рисунке, приведенном выше, выбраны элементы CheckBox "Группировать по категориям" и "Сортировать по категориям и дате". Обратите внимание, что данные группируются по категориям продуктов, а имена категорий приводятся в алфавитном порядке. Из рисунка трудно заметить, что элементы в каждой категории также сортируются по начальной дате. Это делается с использованием представления коллекции. В разделе Привязка к коллекциям обсуждаются представления коллекций.

  • Когда пользователь выбирает элемент, ContentControl отображает подробное описание выбранного элемента. Это называется Сценарий "основной/подробности". В разделе Сценарий "основной/подробности" содержатся сведения об этом типе сценария привязки.

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

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

Добавить страницу списка продуктов

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

На этом рисунке не показана логика проверки, предоставленная в TextBoxStart Date. Если пользователь вводит недопустимую дату (недопустимый формат или прошедшую дату), он будет уведомлен ToolTip и красным восклицательным знаком после TextBox. В разделе Проверка данных обсуждается создание логики проверки.

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

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

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

  • Направление потока данных
  • Что инициирует обновления источника

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

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

Как показано в приведенном выше рисунке, связывание данных является по существу мостом между целью привязки и источником привязки. На рисунке представлены следующие основные концепции связывания данных WPF:

  • Обычно каждая привязка имеет четыре компонента: объект цели привязки, свойство цели, источник привязки и путь к значению используемого источника привязки. Например, если требуется связать содержимое TextBox со свойством Имя объекта Сотрудник, объектом цели является TextBox, свойством цели является свойство Text, используемым значением является Имя, а объектом источника является объект Сотрудник.

  • Свойством цели должно быть свойство зависимостей. Большинство свойств UIElement является свойствами зависимостей, а большинство свойств зависимостей, за исключением свойств, доступных только для чтения, по умолчанию поддерживает связывание данных. (Свойства зависимости можно определить только через типы DependencyObject, а все элементы UIElement производятся от DependencyObject).

  • Хотя на рисунке это не указано, следует иметь в виду, что объект источник привязки может быть не только пользовательским объектом CLR. Связывание данных WPF поддерживает данные в форме объектов CLR и XML. Например, источником связывания может быть UIElement, любой объект списка, объект CLR, связанный с данными ADO.NET или веб-службами или XmlNode, содержащий данные XML. Дополнительные сведения см. в разделе Общие сведения об источниках привязки.

В процессе чтения других разделов Пакет средств разработки программного обеспечения (пакет SDK) важно помнить, что при связывании цель привязки привязывается к источнику привязки. Например, при отображении некоторых базовых данных XML в ListBox с использованием привязки данных, ListBox привязывается к данным XML.

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

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

Как упоминалось ранее и как показывает стрелка на приведенном выше рисунке, поток данных связывания может идти от цели привязки к источнику привязки (например, исходное значение изменяется, когда пользователь изменяет значение TextBox) и/или от источника привязки к цели привязки (например, содержимое TextBox обновляется при изменениях в источнике привязки), если источник привязки предоставляет соответствующие уведомления.

Возможно, требуется, чтобы в приложении пользователи могли изменить данные и передать их обратно объекту источника. Или может потребоваться не предоставлять пользователям возможности обновления источника данных. Это можно регулировать с помощью свойства Mode объекта Binding. На следующем рисунке показаны различные типы потоков данных:

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

  • Связывание OneWay приводит к изменениям свойства источника для автоматического обновления свойства цели, но изменения свойства цели не передаются обратно к свойству источника. Этот тип привязки подходит, если привязка элемента управления неявно доступна только для чтения. Например, можно привязаться к источнику, такому как биржевые сводки, или, возможно, свойство цели не имеет интерфейса для внесения изменений, например цвета фона привязанной к данным таблицы. Если отсутствует необходимость отслеживать изменения свойства цели, можно использовать режим привязки OneWay, при котором удастся избежать издержек режима привязки TwoWay.

  • Тип связывания TwoWay вызывает изменения либо свойства цели, либо свойства источника для автоматического обновления другого. Этот тип привязки подходит для изменяемых форм или других полностью интерактивных сценариев Пользовательский интерфейс. Большинство свойств являются свойствами по умолчанию для связывания OneWay, но некоторые свойства зависимостей (обычно свойства изменяемых пользователями элементов управления, такие как свойство Text элемента TextBox и свойство IsChecked элемента CheckBox) являются свойствами по умолчанию для связывания TwoWay. Определить программный способом, связано ли по умолчанию свойство зависимостей односторонним или двусторонним способом, можно, получив метаданные свойства с помощью GetMetadata, а затем проверив логическое значение свойства BindsTwoWayByDefault.

  • Связывание OneWayToSource является обратным к связыванию OneWay; оно обновляет свойство источника при изменении свойства цели. Одним примером сценария является пересчет значения цели из Пользовательский интерфейс.

  • На рисунке не показана привязка OneTime, которая вызывает инициализацию свойства цели свойством источника, но последующие изменения при этом не распространяются. Это означает, что, если в содержимом данных производятся изменения или меняется объект в контексте данных, изменение отражается в свойстве цели. Этот тип привязки подходит при использовании данных, если для этого подходит моментальный снимок текущего состояния, или данные являются статическими. Этот тип привязки полезен также, если нужно инициализировать свойство цели некоторыми значениями из свойства источника, а контекст данных заранее не известен. По существу, это является простой формой связывания OneWay, которая обеспечивает лучшую производительность в случаях, когда значение цели не изменяется.

Обратите внимание, что для обнаружения изменений в источнике (применимо для связывания OneWay и TwoWay), источник должен реализовывать подходящий механизм уведомления об изменении свойства, такой как INotifyPropertyChanged. Пример реализации класса INotifyPropertyChanged см. в разделе Практическое руководство. Реализация уведомления об изменении свойства.

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

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

Привязки типовTwoWay и OneWayToSource отслеживают изменения свойства цели и передают их обратно к источнику. Это называется обновлением источника. Например, можно изменять текст элемента TextBox для изменения базового значение источника. Как описано в последнем разделе, направление потока данных определяется значением свойства привязки Mode.

Однако обновляется ли значение источника при изменении текста или после завершения изменения текста и отвода указателя мыши от элемента TextBox? Свойство UpdateSourceTrigger привязки определяет, что инициирует обновление источника. Точки стрелок вправо на следующем рисунке показывают роль свойства UpdateSourceTrigger:

Схема UpdateSourceTrigger

Если значение элемента 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 в редактируемой форме (обновляет значения источника только при нажатии пользователем кнопки отправки)

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

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

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

  • Указание источника привязки
  • Указание пути к значению
  • Связывание и выражение привязки

Подводя итог некоторым основным понятиям, описанным в предыдущих разделах, следует сказать, что связывание устанавливается с помощью объекта Binding и каждая привязка обычно состоит из четырех компонентов: цель привязки, свойство цели, источник привязки и путь к используемому значению источника. Этот раздел описывает установку привязки.

Рассмотрим следующий пример, в котором объектом источника привязки является класс с именем MyData, определенный в пространстве имен SDKSample. В качестве демонстрационного примера класс MyData имеет строковое свойство ColorName, установленное в значение "Красный". Таким образом, этот пример создает кнопку с красным фоном.

<DockPanel
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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.

Схема привязки данных

Может вызвать удивление, почему это работает, несмотря на то, что свойство ColorName — строковое, в то время как свойство Background является свойством типа Brush. Это происходит в результате преобразования типов по умолчанию, которое обсуждается в разделе Преобразование данных.

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

Обратите внимание, что в предыдущем примере источник привязки определялся установкой свойства DataContext на элементе DockPanel. Затем Button наследует значение DataContext от DockPanel, являющегося его родительским элементом. Повторим, что объект источника привязки является одним из четырех необходимых компонентов привязки. Таким образом, без указания объекта источника привязки эта привязка не имела бы смысла.

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

<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 используется при установке связывания в ControlTemplate или Style. Дополнительные сведения см. в разделе Практическое руководство. Указание источника привязки.

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

Если источник привязки является объектом, используйте свойство Path для указания значения, используемого для привязки. При связывании данных XML используйте свойство XPath для указания значения. В некоторых случаях удобно применить свойство Path, даже если это данные XML. Например, если требуется получить доступ к свойству "Имя" возвращаемого XmlNode (в результате выполнения запроса XPath), следует использовать свойство Path в дополнении к свойству XPath.

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

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

<ListBox ItemsSource="{Binding}"
         IsSynchronizedWithCurrentItem="true"/>

В приведенном выше примере используется синтаксис пустой привязки: {Привязка}. В этом случае ListBox наследует DataContext от родительского элемента DockPanel (не показан в этом примере). Если путь не указан, по умолчанию производится привязка к всему объекту. Другими словами, в этом примере путь не был указан, так как мы выполнили привязку свойства ItemsSource ко всему объекту. (Подробное обсуждение см. в разделе Привязка к коллекции.)

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

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

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

До разъяснения других функций и использования привязки данных, было бы полезно рассказать о классе BindingExpression. Как было показано в предыдущих разделах, класс Binding является классом высокого уровня для объявления привязки; класс Binding предоставляет множество свойств, которые позволяют указать характеристики привязки. Связанный класс, BindingExpression, является базовым объектом, поддерживающим связь между источником и целью. Привязка содержит всю информацию, которая может использоваться совместно в нескольких выражениях привязки. BindingExpression представляет собой экземпляр выражения, который не может быть общим и который содержит все сведения об экземпляре Binding.

Например, рассмотрим следующую ситуацию, когда myDataObject является экземпляром классаMyData, myBinding является источником объекта Binding, а классMyData представляет собой определенный класс, содержащий строковое свойство MyDataProperty. В этом примере привязывается текстовое содержимое MyText, экземпляр класса TextBlock, к MyDataProperty.

Dim data1 As New MyData(DateTime.Now)
Dim binding1 As New Binding("MyDataProperty")
binding1.Source = data1
Me.myText.SetBinding(TextBlock.TextProperty, binding1)
//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:

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

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

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

Схема привязки данных

Однако, что делать, если вместо свойства строкового типа объект источника привязки имеет свойство Цвет типа 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, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

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

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

Схема привязки данных

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

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

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

  • Используемые данные не обязательно предназначены для изменения текстового значения свойства, а предназначены для изменения некоторых других значений, например, источника изображения, цвета или стиля отображаемого текста. Преобразователи могут использоваться в данном экземпляре для преобразования привязки неподходящего свойства, например, привязки текстового поля к свойству Background ячейки таблицы.

  • К одним и тем же данным может быть привязано более одного элемента управления или несколько свойств элемента управления. В этом случае основная привязка может просто отображать текст, тогда как другие привязки обрабатывают специфичные проблемы отображения, но они по-прежнему используют одну и ту же привязку в качестве источника информации.

  • Пока еще мы не рассматривали MultiBinding, где свойство цели имеет коллекцию привязок. В случае MultiBinding следует использовать пользовательский IMultiValueConverter для получения окончательного значения из значений привязок. Например, цвет может быть вычислен из соотношения красного, синего и зеленого значений, которые могут быть значениями одних и тех же или разных объектов источника привязки. Примеры и другие сведения содержатся на странице класса MultiBinding.

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

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

  • Способы реализации коллекций
  • Представления коллекций

Объект источника привязки может рассматриваться как отдельный объект, свойства которого содержат данные, или как коллекцию данных полиморфных объектов, часто группируемых вместе (например, в результате запроса к базе данных). Пока еще мы обсуждали привязку только к одному объекту, однако привязка к коллекции данных является распространенным сценарием. Например, распространенным сценарием является использование элементов ItemsControl, таких как ListBox, ListView, или TreeView для отображения коллекции данных, как показано в приложении в разделе Понятие о привязке данных .

К счастью, наша основная диаграмма по-прежнему применима. Если привязать ItemsControl к коллекции, диаграмма будет выглядеть следующим образом:

Схема ItemsControl привязки данных

Как показано на этой диаграмме, выполнить привязку ItemsControl к объекту коллекции можно с помощью свойства ItemsSource. Свойство ItemsSource можно представить как содержимое ItemsControl. Обратите внимание, что привязка является привязкой типа OneWay, поскольку свойство ItemsSource по умолчанию поддерживает привязку OneWay.

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

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

WPF предоставляет класс ObservableCollection<T>, который является встроенной реализацией коллекции данных, предоставляющей интерфейс INotifyCollectionChanged. Обратите внимание, что для полной поддержки передачи значений данных от объектов источника в цели каждый объект в коллекции, который поддерживает свойства связывания, должен также реализовывать интерфейс INotifyPropertyChanged. Пример см. в разделе Пример привязки к коллекции. Дополнительные сведения см. в разделе Общие сведения об источниках привязки.

До реализации собственной коллекции рассмотрите возможность использования класса ObservableCollection<T> или одного из существующих классов коллекций, таких как List<T>, Collection<T> и BindingList<T> (среди многих прочих). Если имеется расширенный сценарий и требуется реализовать свою собственную коллекцию, следует рассмотреть возможность использования IList, которая предоставляет коллекцию объектов, к которым можно по отдельности обращаться по индексу и следовательно, максимально быстро.

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

Так как ItemsControl связан с коллекцией данных, существует возможность сортировать, фильтровать или группировать данные. Для этого используется представления коллекций, которые являются классами, реализующими интерфейс ICollectionView.

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

  • Понятие о представлениях коллекций
  • Создание представления
  • Сортировка
  • Фильтрация
  • Группировка
  • Указатели на текущий элемент
  • Сценарий привязки "основной/подробности"

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

Представление коллекции — это слой, расположенный в верхней части связанной исходной коллекции, с помощью которого можно перемещаться по исходной коллекции и просматривать ее содержимое на основе запросов сортировки, фильтрации и группировки, не изменяя саму коллекцию. В представлении коллекции также поддерживается указатель на текущий элемент коллекции. Если в исходной коллекции реализован интерфейс INotifyCollectionChanged, изменения, инициированные событием CollectionChanged, передаются представлениям.

Поскольку представления не изменяют базовые исходные коллекции, каждая исходная коллекция может иметь несколько связанных с ней представлений. Например, можно иметь коллекцию объектов Задача. С помощью представлений можно отображать одни и те же данные различными способами. Например, в левой части страницы можно отображать задачи, отсортированные по приоритету, а справа — сгруппированные по областям.

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

Одним из способов создания и использования представления является непосредственное создание объекта представления, и затем использование его в качестве источника привязки. Для примера рассмотрим приложение Пример привязки данных, продемонстрированное в разделе Понятие о привязке данных . Приложение реализовано таким образом, что ListBox привязывается к представлению коллекции данных, а не к коллекции данных напрямую. Следующий пример извлечен из приложения Пример привязки данных. Класс CollectionViewSource является прокси Язык XAML (Extensible Application Markup Language) для класса, производного от CollectionView. В этом отдельном примере источник Source представления привязан к коллекции AuctionItems (типа ObservableCollection<T>) объекта текущего приложения.

<Window.Resources>


...


<CollectionViewSource 
      Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"   
      x:Key="listingDataView" />


...


</Window.Resources>

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

<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. При этом функции сортировки и фильтрации совместно используются всеми представлениями коллекции для источника данных. Чтобы включить возможность независимой сортировки и фильтрации для каждого представления коллекции, инициализируйте каждое представление коллекции с использованием собственного объекта DataView.

Сортировка

Как уже отмечалось ранее, представления могут применять сортировку для коллекции. Так как данные находятся в базовой коллекции, они могут иметь или не иметь некий порядок следования. Представление коллекции позволяет установить порядок или изменить порядок, используемый по умолчанию, на основе введенных признаков сравнения. Так как это представление данных на стороне клиента, распространенным сценарием является сортировка пользователем столбцов табличных данных по значениям, содержащимся в столбце. С использованием представлений, управляемая пользователем сортировка может применяться еще раз без необходимости внесения изменений в основную коллекцию или создания повторного запроса к содержимому коллекции. Пример см. в разделе Практическое руководство. Сортировка столбцов GridView при нажатии на заголовок.

В следующем примере показано логика сортировки CheckBox "Сортировать по категориям и данным" из приложения Пользовательский интерфейс в разделе Понятие о привязке данных: .

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));
}

Фильтрация

Представления могут применять к коллекции фильтр. Это означает, что несмотря на то, что элемент может существовать в коллекции, его конкретное представление предназначено для отображения только некоторого подмножества полной коллекции. Возможна фильтрация по условию в данных. Например, как это выполняется приложением в разделе Понятие о привязке данных флажок CheckBox "Показывать только товары по сниженным ценам" содержит логику фильтрации товаров, чья стоимость 25 и выше. Следующий код выполняется для установки фильтра ShowOnlyBargainsFilter в качестве обработчика событий Filter при выборе этого CheckBox:

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.

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

В представлениях также присутствует понятие текущего элемента. Существует возможность перемещаться по объектам в представлении коллекции. При переходе перемещается указатель элемента, позволяющий извлечь объект, расположенный в определенном месте в коллекции. Пример см. в разделе Практическое руководство. Перемещение по объектам в Data CollectionView.

Поскольку WPF выполняет привязку к коллекции только через представление коллекции (либо указанное пользователем, либо представление коллекции по умолчанию), для всех привязок к коллекциям имеется указатель на текущий элемент. При привязке к представлению знак косой черты ("/") в значении Path указывает на текущий элемент представления. В приведенном ниже примере контекст данных является представлением коллекции. В первой строке выполняется привязка к коллекции. Во второй строке выполняется привязка к текущему элементу коллекции. В третьей строке выполняется привязка к свойству Description текущего элемента коллекции.

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

Косую черту и синтаксис свойства также можно комбинировать для обработки иерархии коллекций. В приведенном ниже примере выполняется привязка к текущему элементу коллекции Offices, которая является свойством текущего элемента исходной коллекции.

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

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

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

Понятие текущего элемента применимо не только для перемещения элементов в коллекции, но также для сценария привязки "основной/подробности". Для примера рассмотрим приложение Пользовательский интерфейс, продемонстрированное в разделеПонятие о привязке данных раздел еще раз В этом приложении выделение в ListBox определяет содержимое, показанное в ContentControl. При выборе элемента ListBox ContentControl отображает подробные сведения о выбранном элементе, что позволяет поместить выделение другим способом.

Для выполнения сценария необходимо наличие двух или более элементов управления, привязанных к одному и тому же представлению. В следующем примере из Пример привязки данных показана разметка ListBox и ContentControl, которые можно увидеть в приложении Пользовательский интерфейс из раздела Понятие о привязке данных :.

<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). К шаблонам данных мы перейдем в следующем разделе.

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

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

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

Как показано в примере в предыдущем разделе, и элемент управления ListBox, и ContentControl привязаны ко всему объекту коллекции (или точнее, к представлению объекта коллекции) AuctionItem. Без подробных инструкций о том, как отобразить коллекцию данных ListBox отобразит строковое представление каждого объекта в основной коллекции, а ContentControl отобразит строковое представление объекта, к которому он привязан.

Для решения этой проблемы приложение определяет DataTemplate. Как показано в примере в предыдущем разделе, ContentControl явно использует detailsProductListingTemplate DataTemplate. Элемент управления ListBox неявно использует следующий DataTemplate для отображении объектов AuctionItem в коллекции:

<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"/>
            <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:</TextBlock>
            <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="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <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="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <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>

В разделе Понятие о привязке к данным показан пользовательский интерфейс, полученный с помощью этих двух шаблонов DataTemplate . Как можно увидеть из этого моментального снимка, в дополнение к тому, что DataTemplate дают возможность располагать данные в элементах управления, они позволяют определять подходящие визуальные элементы для данных. Например, элементы DataTrigger используются в указанном выше DataTemplate, так что элементыAuctionItem со значением SpecialFeatures для HighLight будут отображаться с оранжевой границей и звездочкой.

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

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

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

  • Связь проверочных правил и привязки
  • Предоставление визуального отклика
  • Процесс проверки

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

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

Модель привязки данных WPF позволяет сопоставить ValidationRules с объектом Binding. Например, рассмотрим XAML для Add Product Listing "Начальная цена" TextBox из раздела Понятие о привязке к данным :

<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>

Свойство ValidationRules получает коллекцию объектов ValidationRule. ExceptionValidationRule является встроенным правилом ValidationRule, которое проверяет наличие исключений, возникших во время обновления свойства источника привязки. В данном конкретном примере свойством источника привязки является StartPrice (целое число), а целевым свойством — TextBox.Text. Когда пользователь вводит значение, которое невозможно преобразовать в целое число, создается исключение, приводящее к тому, что привязка будет помечена как недопустимая.

Можно также создать свои собственные правила проверки, определив класс, производный от класса ValidationRule, и реализовав метод Validate. В следующем примере показано правило, используемое свойством Add Product Listing "Начальная цена" TextBox из раздела Понятие о привязке к данным :

class FutureDateRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        DateTime date;
        try
        {
            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, как показано в следующем примере:

<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 при каждом нажатии клавиши. Это будет обсуждаться далее в разделе "Процесс проверки".

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

Если пользователь вводит недопустимое значение, следует обеспечить некоторый отклик приложения Пользовательский интерфейс на ошибку. Одним из способов обеспечения такого отклика является установка вложенного свойства Validation.ErrorTemplate в пользовательский шаблон ControlTemplate. Как показано в предыдущем подразделе, StartDateEntryForm TextBox использует ErrorTemplate, называемый шаблоном проверки. В следующем примере рассмотрено определение элемента Шаблон проверки:

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

Элемент AdornedElementPlaceholder указывает, куда будет помещен выбранный элемент управления.

Кроме того, для вывода сообщения об ошибке можно использовать ToolTip. И StartDateEntryForm, и StartPriceEntryForm TextBox используют стиль textStyleTextBox, который создает ToolTip, отображающий сообщение об ошибке. В следующем примере рассмотрено определение элемента textStyleTextBox: Вложенное свойство Validation.HasError принимает значение true, если одна или несколько привязок к свойствам связанного элемента вызвали ошибку.

<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 и ToolTip TextBox форма StartDateEntryForm при ошибке проверки выглядит следующим образом:

Ошибка проверки привязки данных

Если привязка Binding имеет правила проверки, но не указан ErrorTemplate на присоединенном элементе управления, для уведомления пользователей об ошибке проверки по умолчанию будет использоваться ErrorTemplate. ErrorTemplate по умолчанию — это шаблон элемента управления, определяющий красную границу графического уровня. С используемым по умолчанию ErrorTemplate и с ToolTip, элемент Пользовательский интерфейс формы 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; в этом случае для каждого правила ValidationRule, свойству ValidationStep которого присвоено значение UpdatedValue, вызывается метод Validate, пока одно из них не вернет ошибку или пока все они не будут выполнены.

  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, и при задании обработчиком привязки значения источника возникает исключение, обработчик привязки проверяет наличие фильтра исключений UpdateSourceExceptionFilter. Имеется возможность использования отклика UpdateSourceExceptionFilter для возможности создания пользовательского обработчика исключений. Если фильтр исключений UpdateSourceExceptionFilter для привязки Binding не указан, обработчик привязки создает объект ValidationError с исключением и добавляет его в коллекцию Validation.Errors связанного элемента.

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

Можно установить вложенное свойство PresentationTraceSources.TraceLevel связанного с привязкой объекта для получения сведений о состоянии конкретной привязки.

См. также

Задачи

Практическое руководство. Привязка к результатам запроса LINQ

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

Основные понятия

Новые возможности в Windows Presentation Foundation 3.5

Оптимизация производительности: привязка данных

Ссылки

DataErrorValidationRule

Другие ресурсы

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

Практические руководства по привязке данных

Журнал изменений

Дата

Изменения

Причина

Июль 2008

Обновлен раздел Процесс проверки, в котором отражены изменения, внесенные пакетом обновления 1.

Изменение функции SP1.