Общие сведения о привязке данныхData Binding Overview

Привязка данных Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) предоставляет приложениям простой и последовательный способ представления данных и взаимодействия с ними.Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) data binding provides a simple and consistent way for applications to present and interact with data. Можно связывать элементы с данными из различных источников данных в виде объектов среда CLRcommon language runtime (CLR) и XMLXML.Elements can be bound to data from a variety of data sources in the form of среда CLRcommon language runtime (CLR) objects and XMLXML. ContentControlнапример Button и ItemsControl, например ListBox и ListView у встроенной возможностью включения гибких стилей для отдельных элементов данных и коллекций элементов данных.ContentControls such as Button and ItemsControls such as ListBox and ListView have built-in functionality to enable flexible styling of single data items or collections of data items. Представления сортировки, фильтрации и группировки могут быть организованы поверх данных.Sort, filter, and group views can be generated on top of the data.

Функции привязки данных в WPFWPF имеют несколько преимуществ перед традиционными моделями, включая широкий диапазон свойств, которые внутренне поддерживают привязку данных, гибкое представление данных ИПUI и четкое разделение бизнес-логики и ИПUI.The data binding functionality in WPFWPF has several advantages over traditional models, including a broad range of properties that inherently support data binding, flexible ИПUI representation of data, and clean separation of business logic from ИПUI.

В этом разделе сначала будут рассмотрены основные для понятия WPFWPF привязки данных, а затем — использование Binding класс и других возможностей привязки данных.This topic first discusses concepts fundamental to WPFWPF data binding and then goes into the usage of the Binding class and other features of data binding.

Понятие привязки данныхWhat Is Data Binding?

Привязка данных — это процесс установки соединения между ИПUI приложения и бизнес-логикой.Data binding is the process that establishes a connection between the application ИПUI and business logic. Если для привязки заданы правильные настройки, а изменения значений данных сопровождаются правильными уведомлениями, привязанные к данным элементы автоматически отражают изменения.If the binding has the correct settings and the data provides the proper notifications, then, when the data changes its value, the elements that are bound to the data reflect changes automatically. Привязка данных может также означать, что, если внешнее представление данных в элементе изменяется, то базовые данные могут автоматически обновляться для отражения изменений.Data binding can also mean that if an outer representation of the data in an element changes, then the underlying data can be automatically updated to reflect the change. Например, если пользователь изменяет значение в TextBox элемент, базовое значение данных автоматически обновляется в соответствии с изменениями.For example, if the user edits the value in a TextBox element, the underlying data value is automatically updated to reflect that change.

Привязка к данным обычно используется для того, чтобы поместить серверный или локальные данные конфигурации в формы или другие элементы управления ИПUI.A typical use of data binding is to place server or local configuration data into forms or other ИПUI controls. В WPFWPF эта концепция расширяется и уже включает привязку широкого диапазона свойств к различным источникам данных.In WPFWPF, this concept is expanded to include the binding of a broad range of properties to a variety of data sources. В WPFWPF свойства зависимости элементов могут быть привязаны к объектам CLRCLR (включая объекты ADO.NETADO.NET или объекты, связанные с веб-службами и веб-свойства) и к данным XMLXML.In WPFWPF, dependency properties of elements can be bound to CLRCLR objects (including ADO.NETADO.NET objects or objects associated with Web Services and Web properties) and XMLXML data.

Привязку данных можно рассмотреть на примере следующего ИПUI приложения со страницы примера привязки данных.For an example of data binding, take a look at the following application ИПUI from the Data Binding Demo:

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

Выше приведен ИПUI приложения, который отображает список лотов аукциона.The above is the ИПUI of an application that displays a list of auction items. Приложение демонстрирует следующие возможности привязки данных.The application demonstrates the following features of data binding:

  • Содержание ListBox привязан к коллекции AuctionItem объектов.The content of the ListBox is bound to a collection of AuctionItem objects. Объект AuctionItem имеет такие свойства, как Description, StartPrice, StartDate, Category, SpecialFeatures и т. д.An AuctionItem object has properties such as Description, StartPrice, StartDate, Category, SpecialFeatures, etc.

  • Данные (AuctionItem объектов) в ListBox является шаблоном, чтобы описание и текущая цена были показаны для каждого элемента.The data (AuctionItem objects) displayed in the ListBox is templated so that the description and the current price are shown for each item. Это делается с помощью DataTemplate.This is done using a DataTemplate. Кроме того, внешний вид каждого элемента зависит от значения SpecialFeatures отображаемого объекта AuctionItem.In addition, the appearance of each item depends on the SpecialFeatures value of the AuctionItem being displayed. Если значением SpecialFeatures объекта AuctionItem является Color, элемент имеет синюю границу.If the SpecialFeatures value of the AuctionItem is Color, the item has a blue border. Если значением является Highlight, элемент имеет оранжевые границы и помечается звездочкой.If the value is Highlight, the item has an orange border and a star. Раздел Создание шаблонов данных содержит сведения о создании шаблонов данных.The Data Templating section provides information about data templating.

  • Пользователя можно группировать, фильтровать или сортировать данные с помощью CheckBoxпредоставленных.The user can group, filter, or sort the data using the CheckBoxes provided. На приведенном выше рисунке, «Группировать по категории» и «Сортировать по категориям и дате» CheckBoxвыбраны.In the image above, the "Group by category" and "Sort by category and date" CheckBoxes are selected. Можно увидеть, что данные группируются по категориям продуктов, а имена категорий приводятся в алфавитном порядке.You may have noticed that the data is grouped based on the category of the product, and the category name is in alphabetical order. Из рисунка трудно заметить, что элементы в каждой категории также сортируются по начальной дате.It is difficult to notice from the image but the items are also sorted by the start date within each category. Это делается с помощью представления коллекции.This is done using a collection view. Представления коллекций рассматриваются в разделе Привязка к коллекциям.The Binding to Collections section discusses collection views.

  • Когда пользователь выбирает элемент, ContentControl отображает сведения о выбранного элемента.When the user selects an item, the ContentControl displays the details of the selected item. Это называется Сценарий привязки "основной-подробности".This is called the Master-Detail scenario. Сведения об этом типе скрипта привязки см. в разделе Сценарий привязки "основной-подробности".The Master-Detail Scenario section provides information about this type of binding scenario.

  • Тип StartDate свойство DateTime, который возвращает дату, включая время с точностью до миллисекунды.The type of the StartDate property is DateTime, which returns a date that includes the time to the millisecond. В этом приложении пользовательский преобразователь использовался для отображения даты в укороченном формате.In this application, a custom converter has been used so that a shorter date string is displayed. Сведения о преобразователях см. в разделе Преобразование данных.The Data Conversion section provides information about converters.

При нажатии кнопки Добавить продукт появляется следующая форма.When the user clicks the Add Product button, the following form comes up:

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

Пользователь может изменить поля формы, просмотреть список продуктов с помощью панелей краткого предварительного просмотра и подробного предварительного просмотра и нажать кнопку Отправить, для добавления данных нового продукта.The user can edit the fields in the form, preview the product listing using the short preview and the more detailed preview panes, and then click submit to add the new product listing. К новой записи будут применимы все существующие функциональные возможности группировки, фильтрации и сортировки.Any existing grouping, filtering and sorting functionalities will apply to the new entry. В этом конкретном случае элемент, введенный на приведенном выше рисунке, будет отображаться как второй элемент в категории Компьютер.In this particular case, the item entered in the above image will be displayed as the second item within the Computer category.

Не на этом рисунке приведена логика проверки, предоставленная в Дата начала TextBox.Not shown in this image is the validation logic provided in the Start Date TextBox. Если пользователь вводит недопустимую дату (недопустимый формат или прошедшую дату), пользователь будет уведомлен с помощью ToolTip и красным восклицательным знаком рядом с полем TextBox.If the user enters an invalid date (invalid formatting or a past date), the user will be notified with a ToolTip and a red exclamation point next to the TextBox. Сведения о создании логики проверки см. в разделе Проверка данных.The Data Validation section discusses how to create validation logic.

Прежде чем перейти к другим описанным выше возможностям связывания данных, в следующем разделе обсудим основные понятия, важные для понимания привязки данных WPFWPF.Before going into the different features of data binding outlined above, we will first discuss in the next section the fundamental concepts that are critical to understanding WPFWPF data binding.

Основные понятия привязки данныхBasic Data Binding Concepts

Независимо от того, какой элемент привязывается и какой источник данных используется, каждая привязка всегда соответствует модели, показанной на следующем рисунке.Regardless of what element you are binding and the nature of your data source, each binding always follows the model illustrated by the following figure:

Схема, показывающая модель привязки данных.

Как показано на приведенном выше рисунке, привязка данных является по существу мостом между целью привязки и источником привязки.As illustrated by the above figure, data binding is essentially the bridge between your binding target and your binding source. На рисунке представлены следующие основные концепции привязки данных WPFWPF.The figure demonstrates the following fundamental WPFWPF data binding concepts:

  • Как правило, каждая привязка имеет четыре компонента: объект цели привязки, свойство цели, источник привязки и путь к значению используемого источника привязки.Typically, each binding has these four components: a binding target object, a target property, a binding source, and a path to the value in the binding source to use. Например, если требуется привязать содержимое TextBox для имя свойство сотрудника объекта является целевым объектом TextBox, целевым свойством является Text свойство, используйте значение имя, и исходный объект является сотрудника объекта.For example, if you want to bind the content of a TextBox to the Name property of an Employee object, your target object is the TextBox, the target property is the Text property, the value to use is Name, and the source object is the Employee object.

  • Целевое свойство должно быть свойством зависимостей.The target property must be a dependency property. Большинство UIElement свойств являются свойствами зависимостей, и большинство свойств зависимостей, за исключением доступных только для чтения, по умолчанию поддерживает привязку данных.Most UIElement properties are dependency properties and most dependency properties, except read-only ones, support data binding by default. (Только DependencyObject типы могут определять свойства зависимостей и все UIElementявляются производными от DependencyObject.)(Only DependencyObject types can define dependency properties and all UIElements derive from DependencyObject.)

  • Несмотря на то что это не указано на рисунке, следует отметить, что источник привязки не обязан быть пользовательским объектом CLRCLR.Although not specified in the figure, it should be noted that the binding source object is not restricted to being a custom CLRCLR object. Привязка данных WPFWPF поддерживает данные в виде объектов CLRCLR и XMLXML.WPFWPF data binding supports data in the form of CLRCLR objects and XMLXML. Представлены некоторые, возможно, источнике привязки UIElement, любой объект списка CLRCLR объекта, связанного с ADO.NETADO.NET данных или веб-службы или XmlNode, содержащий ваш XMLXML данных.To provide some examples, your binding source may be a UIElement, any list object, a CLRCLR object that is associated with ADO.NETADO.NET data or Web Services, or an XmlNode that contains your XMLXML data. Дополнительные сведения см. в разделе Общие сведения об источниках привязки.For more information, see Binding Sources Overview.

В процессе чтения других разделов пакет средств разработки программного обеспечения (SDK)software development kit (SDK) важно помнить, что при связывании цель привязки привязывается к источнику привязки.As you read through other пакет средств разработки программного обеспечения (SDK)software development kit (SDK) topics, it is important to remember that when you are establishing a binding, you are binding a binding target to a binding source. Например, при отображении некоторых базовых XMLXML данные в ListBox с использованием привязки данных, выполняется привязка к ListBox для XMLXML данных.For example, if you are displaying some underlying XMLXML data in a ListBox using data binding, you are binding your ListBox to the XMLXML data.

Чтобы установить привязку, используйте Binding объекта.To establish a binding, you use the Binding object. В остальной части этого раздела обсуждаются многие понятия, связанные с некоторые свойства и использование Binding объекта.The rest of this topic discusses many of the concepts associated with and some of the properties and usage of the Binding object.

Направление потока данныхDirection of the Data Flow

Как упоминалось ранее и как показывает стрелка на приведенном выше рисунке, поток данных привязки можно перейти от целевого объекта привязки к источнику привязки (например, исходное значение изменяется, когда пользователь редактирует значение TextBox) и (или) от источника привязки целевой объект привязки (например, ваш TextBox содержимое обновляется с изменениями в источнике привязки), если источник привязки предоставляет соответствующие уведомления.As mentioned previously and as indicated by the arrow in the figure above, the data flow of a binding can go from the binding target to the binding source (for example, the source value changes when a user edits the value of a TextBox) and/or from the binding source to the binding target (for example, your TextBox content gets updated with changes in the binding source) if the binding source provides the proper notifications.

Возможно, требуется, чтобы в приложении пользователи могли изменить данные и передать их обратно объекту источника.You may want your application to enable users to change the data and propagate it back to the source object. Или может потребоваться не предоставлять пользователям возможности обновления источника данных.Or you may not want to enable users to update the source data. Это можно управлять, задав Mode свойство вашей Binding объекта.You can control this by setting the Mode property of your Binding object. На следующем рисунке показаны различные типы потоков данных.The following figure illustrates the different types of data flow:

Поток данных привязки данныхData binding data flow

  • OneWay Привязка передает изменения свойства источника для автоматического обновления целевого свойства, но изменения свойства цели не передаются обратно к свойству источника.OneWay binding causes changes to the source property to automatically update the target property, but changes to the target property are not propagated back to the source property. Этот тип привязки подходит, если привязываемый элемент управления неявно доступен только для чтения.This type of binding is appropriate if the control being bound is implicitly read-only. Например, можно привязаться к источнику, такому как биржевые сводки, или, возможно, свойство цели не имеет интерфейса для внесения изменений, например цвета фона привязанной к данным таблицы.For instance, you may bind to a source such as a stock ticker or perhaps your target property has no control interface provided for making changes, such as a data-bound background color of a table. Если нет необходимости отслеживать изменения целевого свойства, можно работать в режиме привязки OneWay — в этом случае удастся избежать издержек режима привязки TwoWay.If there is no need to monitor the changes of the target property, using the OneWay binding mode avoids the overhead of the TwoWay binding mode.

  • TwoWay связывание вызывает изменения в свойство источника или целевого свойства для автоматического обновления другого.TwoWay binding causes changes to either the source property or the target property to automatically update the other. Этот тип привязки подходит для изменяемых форм или других полностью интерактивных сценариев ИПUI.This type of binding is appropriate for editable forms or other fully-interactive ИПUI scenarios. Большинство свойств по умолчанию OneWay привязки, но некоторые свойства зависимостей (обычно свойства изменяемых пользователем элементов управления, такие как Text свойство TextBox и IsChecked свойство CheckBox) по умолчанию для TwoWay привязки.Most properties default to OneWay binding, but some dependency properties (typically properties of user-editable controls such as the Text property of TextBox and the IsChecked property of CheckBox) default to TwoWay binding. Существует способ определить программно, использует ли свойство зависимостей односторонние или двухсторонние привязки по умолчанию: для этого нужно получить метаданные этого свойства, воспользовавшись методом GetMetadata, а затем проверить логическое значение свойства BindsTwoWayByDefault.A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata of the property using GetMetadata and then check the Boolean value of the BindsTwoWayByDefault property.

  • OneWayToSource является обратным OneWay связывание; он обновляет свойство источника при изменении свойства цели.OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changes. Одним из примеров является пересчет исходного значения из ИПUI.One example scenario is if you only need to re-evaluate the source value from the ИПUI.

  • Не показано на рисунке является OneTime привязки, который вызывает инициализировать целевое свойство источника, но последующие изменения не распространяются.Not illustrated in the figure is OneTime binding, which causes the source property to initialize the target property, but subsequent changes do not propagate. Это означает, что, если в контексте данных производятся изменения или меняется объект, это изменение не отражается в целевом свойстве.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. Этот тип привязки подходит при использовании данных там, где приемлемо использовать снимок текущего состояния или данные действительно являются статичными.This type of binding is appropriate if you are using data where either a snapshot of the current state is appropriate to use or the data is truly static. Этот тип привязки также является полезным, если нужно инициализировать целевое свойство с использованием какого-либо значения из исходного свойства, а контекст данных заранее неизвестен.This type of binding is also useful if you want to initialize your target property with some value from a source property and the data context is not known in advance. Это, по сути, упрощенная форма привязки OneWay, которая обеспечивает более высокую производительность в случаях, когда исходное значение не меняется.This is essentially a simpler form of OneWay binding that provides better performance in cases where the source value does not change.

Обратите внимание, что для обнаружения изменений в источнике (применимо к OneWay и TwoWay привязок), источник должен реализовывать механизм уведомлений об изменениях соответствующее свойство INotifyPropertyChanged.Note that to detect source changes (applicable to OneWay and TwoWay bindings), the source must implement a suitable property change notification mechanism such as INotifyPropertyChanged. См. в разделе реализация уведомления об изменении свойства пример INotifyPropertyChanged реализации.See Implement Property Change Notification for an example of an INotifyPropertyChanged implementation.

Mode Страницу свойств предоставляет дополнительные сведения о режимах привязки и пример того, как указать направление привязки.The Mode property page provides more information about binding modes and an example of how to specify the direction of a binding.

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

Привязки становятся TwoWay или OneWayToSource отслеживать изменения в свойство цели и распространять их в источнике.Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. Это называется обновлением источника.This is known as updating the source. Например, можно изменять текст элемента TextBox для изменения базового значение источника.For example, you may edit the text of a TextBox to change the underlying source value. Как описано в предыдущем разделе, направление потока данных определяется по значению Mode свойства привязки.As described in the last section, the direction of the data flow is determined by the value of the Mode property of the binding.

Однако обновляется ли значение источника при изменении текста или после завершения изменения текста и отвода указателя мыши от элемента TextBox?However, does your source value get updated while you are editing the text or after you finish editing the text and point your mouse away from the TextBox? UpdateSourceTrigger Свойство привязки определяет, что инициирует обновления источника.The UpdateSourceTrigger property of the binding determines what triggers the update of the source. Точки стрелок вправо на следующем рисунке показывают роль UpdateSourceTrigger свойство:The dots of the right arrows in the following figure illustrate the role of the UpdateSourceTrigger property:

Схема, показывающая роль свойство UpdateSourceTrigger.

Если UpdateSourceTrigger значение PropertyChanged, затем значение указывает правую стрелку действия TwoWay или OneWayToSource привязки обновляется сразу, как изменения целевого свойства.If the UpdateSourceTrigger value is PropertyChanged, then the value pointed to by the right arrow of TwoWay or the OneWayToSource bindings gets updated as soon as the target property changes. Тем не менее если UpdateSourceTrigger значение LostFocus, а затем это значение обновляется только новое значение при свойство цели теряет фокус.However, if the UpdateSourceTrigger value is LostFocus, then that value only gets updated with the new value when the target property loses focus.

Аналогичную Mode свойство, различные свойства зависимостей имеют различное UpdateSourceTrigger значения.Similar to the Mode property, different dependency properties have different default UpdateSourceTrigger values. Значение по умолчанию для большинства свойств зависимостей — PropertyChanged, а свойство Text имеет значение по умолчанию LostFocus.The default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus. Это означает, что источник обновления обычно происходят при изменении изменения свойства цели, что подходит для CheckBoxes и других простых элементов управления.This means that source updates usually happen whenever the target property changes, which is fine for CheckBoxes and other simple controls. Однако для текстовых полей обновления после каждого нажатия клавиши уменьшают производительность и не дают пользователю обычной возможности удаления предыдущего символа и исправления ошибок ввода до того, как новое значение будет зафиксировано.However, for text fields, updating after every keystroke can diminish performance and it denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. Вот почему Text свойство имеет значение по умолчанию LostFocus вместо PropertyChanged.That is why the Text property has a default value of LostFocus instead of PropertyChanged.

См. в разделе UpdateSourceTrigger сведения о том, как найти значение по умолчанию UpdateSourceTrigger значение свойства зависимостей.See the UpdateSourceTrigger property page for information about how to find the default UpdateSourceTrigger value of a dependency property.

Следующая таблица содержит пример сценария для каждого UpdateSourceTrigger с использованием синтаксиса TextBox в качестве примера:The following table provides an example scenario for each UpdateSourceTrigger value using the TextBox as an example:

Значение UpdateSourceTriggerUpdateSourceTrigger value Когда обновляется значение источникаWhen the Source Value Gets Updated Пример сценария для TextBoxExample Scenario for TextBox
LostFocus (значение по умолчанию для TextBox.Text)LostFocus (default for TextBox.Text) Возникает при потере фокуса элементом управления TextBoxWhen the TextBox control loses focus Объект TextBox , связанный с логикой проверки (см. в разделе Проверка данных)A TextBox that is associated with validation logic (see Data Validation section)
Свойство измененоPropertyChanged При вводе в TextBoxAs you type into the TextBox TextBox элементы управления в окне чатаTextBox controls in a chat room window
ЯвныеExplicit Когда приложение вызывает UpdateSourceWhen the application calls UpdateSource TextBox элементы управления в редактируемой форме (обновляет значения источника только в том случае, когда пользователь нажимает кнопку «Отправить»)TextBox controls in an editable form (updates the source values only when the user clicks the submit button)

Пример см. в разделе Практическое руководство. Управление обновлением источника из поля TextBox.For an example, see Control When the TextBox Text Updates the Source.

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

Подводя итог некоторым понятиям, описанным в предыдущих разделах, установить привязку с помощью Binding объекта и каждая привязка обычно состоит из четырех компонентов: привязка целевой, свойство цели, источник привязки и путь к используемому значению источника.To recapitulate some of the concepts discussed in the previous sections, you establish a binding using the Binding object, and each binding usually has four components: binding target, target property, binding source, and a path to the source value to use. Этот раздел описывает установку привязки.This section discusses how to set up a binding.

Рассмотрим следующий пример, в котором объектом источника привязки является класс с именем MyData, определенный в пространстве имен SDKSample.Consider the following example, in which the binding source object is a class named MyData that is defined in the SDKSample namespace. В качестве демонстрационного примера класс MyData имеет строковое свойство с именем ColorName со значением Red.For demonstration purposes, MyData class has a string property named ColorName, of which the value is set to "Red". Таким образом, в этом примере создается кнопка с красным фоном.Thus, this example generates a button with a red background.

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

Дополнительные сведения о синтаксисе объявления привязки и примеры настройки привязки в коде см. в разделе Общие сведения об объявлении привязок.For more details on the binding declaration syntax and for examples of how to set up a binding in code, see Binding Declarations Overview.

Если применить этот пример к основной диаграмме, полученное изображение будет выглядеть следующим образом.If we apply this example to our basic diagram, the resulting figure looks like the following. Это OneWay привязке, так как свойство Background поддерживает OneWay привязки по умолчанию.This is a OneWay binding because the Background property supports OneWay binding by default.

Схема, показывающая свойства Background привязки данных.

Может возникнуть вопрос, почему это работает, даже если ColorName свойство имеет строковый тип при Background свойство имеет тип Brush.You may wonder why this works even though the ColorName property is of type string while the Background property is of type Brush. Это происходит в результате преобразования типов по умолчанию, которое обсуждается в разделе Преобразование данных.This is default type conversion at work and is discussed in the Data Conversion section.

Указание источника привязкиSpecifying the Binding Source

Обратите внимание на то, что в предыдущем примере источник привязки определялся установкой DataContext свойство DockPanel элемент.Notice that in the previous example, the binding source is specified by setting the DataContext property on the DockPanel element. Button Затем наследует DataContext значение из DockPanel, который является его родительским элементом.The Button then inherits the DataContext value from the DockPanel, which is its parent element. Повторим, что объект источника привязки является одним из четырех необходимых компонентов привязки.To reiterate, the binding source object is one of the four necessary components of a binding. Таким образом, без указания объекта источника привязки эта привязка не имела бы смысла.Therefore, without the binding source object being specified, the binding would do nothing.

Есть несколько способов для указания объекта источника привязки.There are several ways to specify the binding source object. С помощью DataContext на родительский элемент может быть удобно при привязке нескольких свойств к одному источнику.Using the DataContext property on a parent element is useful when you are binding multiple properties to the same source. Однако иногда удобнее указывать источник привязки в отдельных объявлениях привязки.However, sometimes it may be more appropriate to specify the binding source on individual binding declarations. Для предыдущего примера, вместо использования DataContext свойство, можно указать источник привязки, задав Source свойства непосредственно в объявлении привязки кнопки, как показано в следующем примере:For the previous example, instead of using the DataContext property, you can specify the binding source by setting the Source property directly on the binding declaration of the button, as in the following example:

<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 свойство, чтобы указать источник привязки.Other than setting the DataContext property on an element directly, inheriting the DataContext value from an ancestor (such as the button in the first example), and explicitly specifying the binding source by setting the Source property on the Binding (such as the button the last example), you can also use the ElementName property or the RelativeSource property to specify the binding source. ElementName Свойство полезно, если при привязке к другим элементам в приложении, например при использовании ползунка для настройки ширины кнопки.The ElementName property is useful when you are binding to other elements in your application, such as when you are using a slider to adjust the width of a button. RelativeSource Свойство полезно, если привязка задается в ControlTemplate или Style.The RelativeSource property is useful when the binding is specified in a ControlTemplate or a Style. Дополнительные сведения см. в разделе Указание источника привязки.For more information, see Specify the Binding Source.

Указание пути к значениюSpecifying the Path to the Value

Если источник привязки является объектом, то использовать Path свойство, чтобы указать значение, используемое для привязки.If your binding source is an object, you use the Path property to specify the value to use for your binding. Если при привязке к XMLXML данных, использовать XPath свойство, чтобы указать значение.If you are binding to XMLXML data, you use the XPath property to specify the value. В некоторых случаях, возможно, применяемой к использованию Path свойство даже в том случае, когда база данных находится XMLXML.In some cases, it may be applicable to use the Path property even when your data is XMLXML. Например, если вы хотите получить доступ к свойству Name возвращаемого XmlNode (в результате запроса XPath), следует использовать Path свойства в дополнение к XPath свойство.For example, if you want to access the Name property of a returned XmlNode (as a result of an XPath query), you should use the Path property in addition to the XPath property.

Сведения о синтаксисе и примеры см. в разделе Path и XPath страницы свойств.For syntax information and examples, see the Path and XPath property pages.

Обратите внимание, что, несмотря на то, что мы и подчеркнули, Path к используемому значению является одним из четырех необходимых компонентов привязки, в сценариях, когда вы хотите выполнить привязку ко всему объекту, используемое значение будет таким же, как объект источника привязки.Note that although we have emphasized that the Path to the value to use is one of the four necessary components of a binding, in the scenarios which you want to bind to an entire object, the value to use would be the same as the binding source object. В таком случае это касается и не указывайте Path.In those cases, it is applicable to not specify a Path. Рассмотрим следующий пример.Consider the following example:

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

В приведенном выше примере используется синтаксис пустой привязки: {Binding}.The above example uses the empty binding syntax: {Binding}. В этом случае ListBox наследует DataContext от родительского элемента DockPanel (не показано в следующем примере).In this case, the ListBox inherits the DataContext from a parent DockPanel element (not shown in this example). Если путь не указан, по умолчанию производится привязка ко всему объекту.When the path is not specified, the default is to bind to the entire object. Другими словами, в этом примере путь был указан, так как выполняется привязка ItemsSource свойство ко всему объекту.In other words, in this example, the path has been left out because we are binding the ItemsSource property to the entire object. (Подробное описание см. в разделе Привязка к коллекциям.)(See the Binding to Collections section for an in-depth discussion.)

Кроме привязки к коллекции, этот сценарий полезен также для привязки ко всему объекту, а не только к одному свойству объекта.Other than binding to a collection, this scenario is also useful when you want to bind to an entire object instead of just a single property of an object. Например, если объект источника является объектом строкового типа и всего лишь нужна привязка к самой строке.For example, if your source object is of type string and you simply want to bind to the string itself. Другим распространенным сценарием является необходимость привязки элемента к объекту с несколькими свойствами.Another common scenario is when you want to bind an element to an object with several properties.

Обратите внимание, что может потребоваться применить пользовательскую логику, чтобы данные имели смысл для свойства целевого объекта привязки.Note that you may need to apply custom logic so that the data is meaningful to your bound target property. Пользовательская логика может иметь вид пользовательского преобразователя (если тип преобразования по умолчанию не существует).The custom logic may be in the form of a custom converter (if default type conversion does not exist). Сведения о преобразователях см. в разделе Преобразование данных.See Data Conversion for information about converters.

Привязка и класс BindingExpressionBinding and BindingExpression

До разъяснения других функций и использования привязки данных, было бы полезно рассказать BindingExpression класса.Before getting into other features and usages of data binding, it would be useful to introduce the BindingExpression class. Как видно в предыдущих разделах, Binding класс является классом высокого уровня для объявления привязки; Binding класс предоставляет множество свойств, которые позволяют указать характеристики привязки.As you have seen in previous sections, the Binding class is the high-level class for the declaration of a binding; the Binding class provides many properties that allow you to specify the characteristics of a binding. Связанный класс, BindingExpression, является базовым объектом, поддерживающим связь между источником и целью.A related class, BindingExpression, is the underlying object that maintains the connection between the source and the target. Привязка содержит всю информацию, которая может использоваться совместно в нескольких выражениях привязки.A binding contains all the information that can be shared across several binding expressions. Объект BindingExpression представляет собой экземпляр выражения, который нельзя использовать совместно и содержит все сведения об экземпляре Binding.A BindingExpression is an instance expression that cannot be shared and contains all the instance information of the Binding.

Например, рассмотрим следующую команду, где myDataObject является экземпляром класса MyData класс, myBinding является источником Binding объекта и MyData класс представляет собой определенный класс, который содержит строковое свойство с именем MyDataProperty.For example, consider the following, where myDataObject is an instance of MyData class, myBinding is the source Binding object, and MyData class is a defined class that contains a string property named MyDataProperty. В этом примере привязывается текстовое содержимое mytext, экземпляр TextBlock, MyDataProperty.This example binds the text content of mytext, an instance of TextBlock, to MyDataProperty.

// Make a new source.
MyData myDataObject = new MyData(DateTime.Now);      
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
// Bind the new data source to the myText TextBlock control's Text dependency property.
myText.SetBinding(TextBlock.TextProperty, myBinding);
' Make a new source.
Dim data1 As New MyData(DateTime.Now)
Dim binding1 As New Binding("MyDataProperty")
binding1.Source = data1
' Bind the new data source to the myText TextBlock control's Text dependency property.
Me.myText.SetBinding(TextBlock.TextProperty, binding1)

Один и тот же объект myBinding можно использовать для создания других привязок.You can use the same myBinding object to create other bindings. Например, можно использовать объект myBinding для привязки текстового содержимого флажка к MyDataProperty.For example, you may use myBinding object to bind the text content of a check box to MyDataProperty. В этом сценарии будут два экземпляра BindingExpression совместное использование myBinding объекта.In that scenario, there will be two instances of BindingExpression sharing the myBinding object.

Объект BindingExpression объекта можно получить с помощью возвращаемого значения метода GetBindingExpression в объекте с привязкой к данным.A BindingExpression object can be obtained through the return value of calling GetBindingExpression on a data-bound object. В следующих разделах описываются некоторые примеры использования BindingExpression класса:The following topics demonstrate some of the usages of the BindingExpression class:

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

В предыдущем примере кнопка красная так как его Background свойство привязано к строковому свойству со значением «Красный».In the previous example, the button is red because its Background property is bound to a string property with the value "Red". Это работает, поскольку преобразователь типов присутствует на Brush тип преобразовать строковое значение для Brush.This works because a type converter is present on the Brush type to convert the string value to a Brush.

Если добавить эти сведения в рисунок из раздела Создание привязки, схема будет выглядеть следующим образом.To add this information to the figure in the Creating a Binding section, the diagram looks like the following:

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

Однако, что делать, если вместо свойства строкового типа объект источника привязки имеет цвет свойство типа Color?However, what if instead of having a property of type string your binding source object has a Color property of type Color? В этом случае в порядке для создания привязки необходимо включить первый цвет значение свойства в нечто, Background значение свойства.In that case, in order for the binding to work you would need to first turn the Color property value into something that the Background property accepts. Необходимо создать пользовательский преобразователь, реализовав IValueConverter интерфейс, как показано в следующем примере:You would need to create a custom converter by implementing the IValueConverter interface, as in the following example:

[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;
    }
}
<ValueConversion(GetType(Color), GetType(SolidColorBrush))>
Public Class ColorBrushConverter
    Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
        Dim color As Color = CType(value, Color)
        Return New SolidColorBrush(color)
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return Nothing
    End Function
End Class

IValueConverter Справочной странице предоставляет дополнительные сведения.The IValueConverter reference page provides more information.

Теперь пользовательский преобразователь используется вместо преобразования по умолчанию и схема выглядит следующим образом.Now the custom converter is used instead of default conversion, and our diagram looks like this:

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

Таким образом, преобразования по умолчанию могут быть доступны благодаря преобразователям типов, присутствующим в типе, к которому производится привязка.To reiterate, default conversions may be available because of type converters that are present in the type being bound to. Такое поведение будет зависеть от того, какие преобразователи типов доступны в целевом объекте.This behavior will depend on which type converters are available in the target. Если существуют какие-то сомнением, создайте свой собственный преобразователь.If in doubt, create your own converter.

Ниже приведены некоторые типовые сценарии, где имеет смысл реализация преобразователя данных.Following are some typical scenarios where it makes sense to implement a data converter:

  • Данные должны отображаться по-разному в зависимости от региональных стандартов.Your data should be displayed differently, depending on culture. Например, можно реализовать преобразователь валюты или преобразователь даты/времени в календаре на основе значений или стандартов, используемых в определенных региональных стандартах.For instance, you might want to implement a currency converter or a calendar date/time converter based on the values or standards used in a particular culture.

  • Используемые данные не обязательно предназначены для изменения текстового значения свойства, а предназначены для изменения некоторых других значений, например источника изображения, цвета или стиля отображаемого текста.The data being used is not necessarily intended to change the text value of a property, but is instead intended to change some other value, such as the source for an image, or the color or style of the display text. Преобразователи могут использоваться в данном экземпляре для преобразования привязки неподходящего свойства, например привязки текстового поля к свойству Background ячейки таблицы.Converters can be used in this instance by converting the binding of a property that might not seem to be appropriate, such as binding a text field to the Background property of a table cell.

  • К одним и тем же данным может быть привязано несколько элементов управления или несколько свойств элементов управления.More than one control or to multiple properties of controls are bound to the same data. В этом случае основная привязка может просто отображать текст, тогда как другие привязки обрабатывают специфичные проблемы отображения, но они по-прежнему используют одну и ту же привязку в качестве исходных данных.In this case, the primary binding might just display the text, whereas other bindings handle specific display issues but still use the same binding as source information.

  • Пока мы еще не рассматривали MultiBinding, где свойство цели имеет коллекцию привязок.So far we have not yet discussed MultiBinding, where a target property has a collection of bindings. В случае использования MultiBinding, следует использовать пользовательский IMultiValueConverter для получения окончательного значения из значений привязок.In the case of a MultiBinding, you use a custom IMultiValueConverter to produce a final value from the values of the bindings. Например, цвет может быть вычислен из соотношения красного, синего и зеленого значений, которые могут быть значениями одних и тех же или разных объектов источника привязки.For example, color may be computed from red, blue, and green values, which can be values from the same or different binding source objects. См. в разделе MultiBinding класс страницы, примеры и Дополнительные сведения.See the MultiBinding class page for examples and information.

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

Объект источника привязки может рассматриваться как отдельный объект, свойства которого содержат данные, или как коллекция данных полиморфных объектов, часто группируемых вместе (например, в результате запроса к базе данных).A binding source object can be treated either as a single object of which the properties contain data or as a data collection of polymorphic objects that are often grouped together (such as the result of a query to a database). Пока еще мы обсуждали привязку только к одному объекту, однако привязка к коллекции данных является распространенным сценарием.So far we've only discussed binding to single objects, however, binding to a data collection is a common scenario. Например, распространенным сценарием является использование ItemsControl например ListBox, ListView, или TreeView для отображения коллекции данных, такие как в приложении, показанном в новые возможности привязки данных? раздел.For example, a common scenario is to use an ItemsControl such as a ListBox, ListView, or TreeView to display a data collection, such as in the application shown in the What Is Data Binding? section.

К счастью, наша основная схема по-прежнему применима.Fortunately, our basic diagram still applies. При связывании ItemsControl коллекции, то диаграмма будет выглядеть следующим образом:If you are binding an ItemsControl to a collection, the diagram looks like this:

Схема, показывающая объект ItemsControl привязки данных.

Как показано на этой схеме для привязки ItemsControl на объект коллекции ItemsSource свойством является свойство для использования.As shown in this diagram, to bind an ItemsControl to a collection object, ItemsSource property is the property to use. Можно представить себе ItemsSource свойство как содержимое ItemsControl.You can think of ItemsSource property as the content of the ItemsControl. Обратите внимание, что привязка OneWay поскольку ItemsSource поддерживает свойство OneWay привязки по умолчанию.Note that the binding is OneWay because the ItemsSource property supports OneWay binding by default.

Способы реализации коллекцийHow to Implement Collections

Пользователь может выполнить перечисление любой коллекции, реализующей IEnumerable интерфейс.You can enumerate over any collection that implements the IEnumerable interface. Тем не менее чтобы настроить динамические привязки таким образом, чтобы обновить вставки и удаления элементов в коллекции ИПUI автоматически, в коллекции должен быть реализован INotifyCollectionChanged интерфейс.However, to set up dynamic bindings so that insertions or deletions in the collection update the ИПUI automatically, the collection must implement the INotifyCollectionChanged interface. Этот интерфейс предоставляет событие, которое должно вызываться при каждом изменении коллекции.This interface exposes an event that should be raised whenever the underlying collection changes.

WPFWPF предоставляет ObservableCollection<T> класс, который является встроенной реализацией коллекции данных, предоставляющей INotifyCollectionChanged интерфейс.provides the ObservableCollection<T> class, which is a built-in implementation of a data collection that exposes the INotifyCollectionChanged interface. Обратите внимание, что для полной поддержки передачи значений данных от объектов источника для целевых объектов, каждый объект в коллекции, который поддерживает свойства связывания должен также реализовывать INotifyPropertyChanged интерфейс.Note that to fully support transferring data values from source objects to targets, each object in your collection that supports bindable properties must also implement the INotifyPropertyChanged interface. Дополнительные сведения см. в разделе Общие сведения об источниках привязки.For more information, see Binding Sources Overview.

Перед реализацией свою собственную коллекцию, рассмотрите возможность использования ObservableCollection<T> или один из существующей коллекции классов, таких как List<T>, Collection<T>, и BindingList<T>, среди прочих.Before implementing your own collection, consider using ObservableCollection<T> or one of the existing collection classes, such as List<T>, Collection<T>, and BindingList<T>, among many others. Если имеется расширенный скрипт и требуется реализовать свою собственную коллекцию, рассмотрите возможность использования IList, который предоставляет неуниверсальную коллекцию объектов, которые можно получить индивидуальный доступ по индексу и, следовательно, максимальную производительность.If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index and thus the best performance.

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

Один раз в ItemsControl привязан к коллекции данных, может потребоваться сортировка, фильтрация и группировать данные.Once your ItemsControl is bound to a data collection, you may want to sort, filter, or group the data. Чтобы сделать это, используйте представления коллекций, которые являются классами, реализующими ICollectionView интерфейс.To do that, you use collection views, which are classes that implement the ICollectionView interface.

Понятие о представлениях коллекцийWhat Are Collection Views?

Представление коллекции — это слой, расположенный в верхней части связанной исходной коллекции, с помощью которого можно перемещаться по исходной коллекции и просматривать ее содержимое на основе запросов сортировки, фильтрации и группировки, не изменяя саму коллекцию.A collection view is a layer on top of a binding source collection that allows you to navigate and display the source collection based on sort, filter, and group queries, without having to change the underlying source collection itself. В представлении коллекции также поддерживается указатель на текущий элемент коллекции.A collection view also maintains a pointer to the current item in the collection. Если в исходной коллекции реализован INotifyCollectionChanged интерфейс, изменения, инициированные CollectionChanged событие, передаются представлениям.If the source collection implements the INotifyCollectionChanged interface, the changes raised by the CollectionChanged event are propagated to the views.

Так как представления не меняют базовые исходные коллекции, каждая исходная коллекция может иметь несколько связанных с ней представлений.Because views do not change the underlying source collections, each source collection can have multiple views associated with it. Например, имеется коллекция объектов Task.For example, you may have a collection of Task objects. С помощью представлений можно отображать одни и те же данные различными способами.With the use of views, you can display that same data in different ways. Например, в левой части страницы можно отображать задачи, отсортированные по приоритету, а справа — сгруппированные по областям.For example, on the left side of your page you may want to show tasks sorted by priority, and on the right side, grouped by area.

Создание представленияHow to Create a View

Одним из способов создания и использования представления является непосредственное создание объекта представления и затем использование его в качестве источника привязки.One way to create and use a view is to instantiate the view object directly and then use it as the binding source. В качестве примера рассмотрим приложение Пример привязки данных, показанное в подразделе Понятие привязки данных.For example, consider the Data Binding Demo application shown in the What Is Data Binding? section. Приложение реализовано таким образом, чтобы ListBox привязывается к представлению коллекции данных, а не в коллекции данных напрямую.The application is implemented such that the ListBox binds to a view over the data collection instead of the data collection directly. Следующий пример извлекается из приложения Пример привязки данных.The following example is extracted from the Data Binding Demo application. CollectionViewSource Класс является Язык XAMLExtensible Application Markup Language (XAML) прокси-сервера, который наследует от класса CollectionView.The CollectionViewSource class is the Язык XAMLExtensible Application Markup Language (XAML) proxy of a class that inherits from CollectionView. В данном конкретном примере Source представления привязан к AuctionItems коллекции (типа ObservableCollection<T>) текущего объекта приложения.In this particular example, the Source of the view is bound to the AuctionItems collection (of type ObservableCollection<T>) of the current application object.

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

Ресурс listingDataView выступает в качестве источника привязки для элементов в приложении, такие как ListBox:The resource listingDataView then serves as the binding source for elements in the application, such as the ListBox:

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"
    ItemsSource="{Binding Source={StaticResource listingDataView}}">
</ListBox>

Чтобы создать другое представление для той же коллекции, можно создать другое CollectionViewSource экземпляра и присвоить ему другое x:Key имя.To create another view for the same collection, you can create another CollectionViewSource instance and give it a different x:Key name.

В следующей таблице показано, какие типы данных представления создаются в качестве представления коллекции по умолчанию или с помощью CollectionViewSource зависимости от типа исходной коллекции.The following table shows which view data types are created as the default collection view or by CollectionViewSource based on the source collection type.

Тип исходной коллекцииSource collection type Тип представления коллекцииCollection view type ПримечанияNotes
IEnumerable Внутренний тип, основанный на CollectionViewAn internal type based on CollectionView Невозможно группировать элементы.Cannot group items.
IList ListCollectionView Самый быстрый.Fastest.
IBindingList BindingListCollectionView
Использование представления по умолчаниюUsing a Default View

Один из способов создания и использования представления коллекции заключается в указании представления коллекции в качестве источника привязки.Specifying a collection view as a binding source is one way to create and use a collection view. WPF также создает представление коллекции по умолчанию для каждой коллекции, используемой в качестве источника привязки.WPF also creates a default collection view for every collection used as a binding source. Если выполнить привязку непосредственно к коллекции, WPF выполняет привязку к представлению коллекции по умолчанию.If you bind directly to a collection, WPF binds to its default view. Обратите внимание, что данное представление по умолчанию совместно используется всеми привязками к одной и той же коллекции, поэтому изменения, внесенные в представление по умолчанию одним привязанным элементом управления либо кодом (например, сортировка или изменение указателя на текущий элемент, что будет рассмотрено ниже), распространяются на все привязки к одной коллекции.Note that this default view is shared by all bindings to the same collection, so a change made to a default view by one bound control or code (such as sorting or a change to the current item pointer, discussed later) is reflected in all other bindings to the same collection.

Чтобы получить представление по умолчанию, используйте GetDefaultView метод.To get the default view, you use the GetDefaultView method. Пример см. в разделе Практическое руководство. Получение представления по умолчанию для коллекции данных.For an example, see Get the Default View of a Data Collection.

Использование представлений коллекций с таблицами данных ADO.NETCollection Views with ADO.NET DataTables

Для повышения производительности представления коллекций для ADO.NET DataTable или DataView объектов делегируют функции сортировки и фильтрации для DataView.To improve performance, collection views for ADO.NET DataTable or DataView objects delegate sorting and filtering to the DataView. При этом функции сортировки и фильтрации совместно используются всеми представлениями коллекции для источника данных.This causes sorting and filtering to be shared across all collection views of the data source. Чтобы включить для независимой сортировки и фильтрации для каждого представления коллекции, инициализируйте каждое представление коллекции с собственным DataView объекта.To enable each collection view to sort and filter independently, initialize each collection view with its own DataView object.

СортировкаSorting

Как уже отмечалось ранее, представления могут применять сортировку для коллекции.As mentioned before, views can apply a sort order to a collection. Так как данные находятся в базовой коллекции, они могут иметь или не иметь некий порядок следования.As it exists in the underlying collection, your data may or may not have a relevant, inherent order. Представление коллекции позволяет установить порядок или изменить порядок, используемый по умолчанию, на основе введенных признаков сравнения.The view over the collection allows you to impose an order, or change the default order, based on comparison criteria that you supply. Так как это представление данных на стороне клиента, распространенным скриптом является сортировка пользователем столбцов табличных данных по значениям, содержащимся в столбце.Because it is a client-based view of the data, a common scenario is that the user might want to sort columns of tabular data per the value that the column corresponds to. С использованием представлений управляемая пользователем сортировка может применяться еще раз без необходимости внесения изменений в основную коллекцию или создания повторного запроса к содержимому коллекции.Using views, this user-driven sort can be applied, again without making any changes to the underlying collection or even having to requery for the collection content. Пример см. в разделе Практическое руководство. Сортировка столбцов GridView при нажатии на заголовок.For an example, see Sort a GridView Column When a Header Is Clicked.

В следующем примере показано логика сортировки «Сортировать по категориям и дате» CheckBox приложения ИПUI в новые возможности привязки данных? раздел:The following example shows the sorting logic of the "Sort by category and date" CheckBox of the application ИПUI in the What Is Data Binding? section:

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));
}
Private Sub AddSorting(ByVal sender As Object, ByVal args As RoutedEventArgs)
    '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))
End Sub

ФильтрацияFiltering

Представления могут применять к коллекции фильтр.Views can also apply a filter to a collection. Это означает, что несмотря на то что элемент может существовать в коллекции, его конкретное представление предназначено для отображения только некоторого подмножества полной коллекции.This means that although an item might exist in the collection, this particular view is intended to show only a certain subset of the full collection. Возможна фильтрация по условию в данных.You might filter on a condition in the data. Например, как показано в приложение в новые возможности привязки данных? разделе «Показывать только товары по сниженным ценам» CheckBox содержит логику фильтрации товаров с ценой 25 долл.For instance, as is done by the application in the What Is Data Binding? section, the "Show only bargains" CheckBox contains logic to filter out items that cost $25 or more. Следующий код выполняется для установки ShowOnlyBargainsFilter как Filter обработчик событий при, CheckBox выбран:The following code is executed to set ShowOnlyBargainsFilter as the Filter event handler when that CheckBox is selected:

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);
AddHandler listingDataView.Filter, AddressOf ShowOnlyBargainsFilter

Обработчик события ShowOnlyBargainsFilter реализуется следующим образом.The ShowOnlyBargainsFilter event handler has the following implementation:

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;
        }
    }
}
Private Sub ShowOnlyBargainsFilter(ByVal sender As Object, ByVal e As FilterEventArgs)
    Dim product As AuctionItem = CType(e.Item, AuctionItem)
    If Not (product Is Nothing) Then
        'Filter out products with price 25 or above
        If product.CurrentPrice < 25 Then
            e.Accepted = True
        Else
            e.Accepted = False
        End If
    End If
End Sub

Если вы используете один из CollectionView классы напрямую вместо того CollectionViewSource, использовалась бы Filter свойство, чтобы указать обратный вызов.If you are using one of the CollectionView classes directly instead of CollectionViewSource, you would use the Filter property to specify a callback. Пример см. в разделе Практическое руководство. Фильтрация данных в представлении.For an example, see Filter Data in a View.

ГруппированиеGrouping

За исключением внутреннего класса, IEnumerable коллекции, все представления коллекций поддерживают функцию группировки, которая позволяет разбить коллекцию в представлении коллекции на логические группы.Except for the internal class that views an IEnumerable collection, all collection views support the functionality of grouping, which allows the user to partition the collection in the collection view into logical groups. Группы могут быть явными, если пользователь предоставляет список групп, или неявными, если эти группы создаются динамически в зависимости от данных.The groups can be explicit, where the user supplies a list of groups, or implicit, where the groups are generated dynamically depending on the data.

В следующем примере показано логику «Группировать по категории» CheckBox:The following example shows the logic of the "Group by category" CheckBox:

// This groups the items in the view by the property "Category"
PropertyGroupDescription groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);
'This groups by property "Category"
Dim groupDescription As PropertyGroupDescription = New PropertyGroupDescription
groupDescription.PropertyName = "Category"
listingDataView.GroupDescriptions.Add(groupDescription)

Другой пример группировки см. в разделе Практическое руководство. Группировка элементов в объекте ListView, реализующем GridView.For another grouping example, see Group Items in a ListView That Implements a GridView.

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

В представлениях также присутствует понятие текущего элемента.Views also support the notion of a current item. Существует возможность перемещаться по объектам в представлении коллекции.You can navigate through the objects in a collection view. При переходе перемещается указатель элемента, позволяющий извлечь объект, расположенный в определенном месте в коллекции.As you navigate, you are moving an item pointer that allows you to retrieve the object that exists at that particular location in the collection. Пример см. в разделе Перемещение по объектам в Data CollectionView.For an example, see Navigate Through the Objects in a Data CollectionView.

Поскольку WPF выполняет привязку к коллекции только с помощью представления (либо указанного пользователем, либо представления коллекции по умолчанию), для всех привязок к коллекциям имеется указатель на текущий элемент.Because WPF binds to a collection only by using a view (either a view you specify, or the collection's default view), all bindings to collections have a current item pointer. При привязке к представлению символ косой черты ("/") в значении Path указывает на текущий элемент представления.When binding to a view, the slash ("/") character in a Path value designates the current item of the view. В следующем примере контекст данных является представлением коллекции.In the following example, the data context is a collection view. В первой строке выполняется привязка к коллекции.The first line binds to the collection. Во второй строке выполняется привязка к текущему элементу коллекции.The second line binds to the current item in the collection. В третьей строке выполняется привязка к свойству Description текущего элемента коллекции.The third line binds to the Description property of the current item in the collection.

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

Косую черту и синтаксис свойства также можно комбинировать для обработки иерархии коллекций.The slash and property syntax can also be stacked to traverse a hierarchy of collections. В приведенном ниже примере выполняется привязка к текущему элементу коллекции Offices, который является свойством текущего элемента исходной коллекции.The following example binds to the current item of a collection named Offices, which is a property of the current item of the source collection.

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

На указатель текущего элемента влияют примененные к коллекции операции сортировки и фильтрации.The current item pointer can be affected by any sorting or filtering that is applied to the collection. При сортировке указатель текущего элемента устанавливается на последний выбранный элемент, однако представление коллекции перестраивается относительно его.Sorting preserves the current item pointer on the last item selected, but the collection view is now restructured around it. (Возможно, до этого выбранный элемент был в начале списка, но теперь выбранный элемент может оказаться где-нибудь в середине.) При фильтрации выбранный элемент сохраняется, если данный выбор остается в представлении после фильтрации.(Perhaps the selected item was at the beginning of the list before, but now the selected item might be somewhere in the middle.) Filtering preserves the selected item if that selection remains in view after the filtering. В противном случае указатель текущего элемента устанавливается на первый элемент отфильтрованного представления коллекции.Otherwise, the current item pointer is set to the first item of the filtered collection view.

Сценарий "основной — подробности"Master-Detail Binding Scenario

Понятие текущего элемента применимо не только для перемещения элементов в коллекции, но также для сценария привязки "основной — подробности".The notion of a current item is useful not only for navigation of items in a collection, but also for the master-detail binding scenario. Еще раз рассмотрим ИПUI приложения из подраздела Понятие привязки данных.Consider the application ИПUI in the What Is Data Binding? section again. В этом приложении выделение в ListBox определяет содержимое, показанное в ContentControl.In that application, the selection within the ListBox determines the content shown in the ContentControl. Чтобы поместить его в другой способ, при ListBox элемент выделен, ContentControl отображает сведения о выбранного элемента.To put it in another way, when a ListBox item is selected, the ContentControl shows the details of the selected item.

Для реализации этого сценария необходимо наличие двух или более элементов управления, привязанных к одному и тому же представлению.You can implement the master-detail scenario simply by having two or more controls bound to the same view. В следующем примере из пример привязки данных показана разметка элементов ListBox и ContentControl появится в приложении ИПUI в новые возможности привязки данных? раздел:The following example from the Data Binding Demo shows the markup of the ListBox and the ContentControl you see on the application ИПUI in the What Is Data Binding? section:

<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 (просмотреть определение этого ресурса можно в подразделе Создание представления).Notice that both of the controls are bound to the same source, the listingDataView static resource (see the definition of this resource in the How to Create a View section). Это работает, поскольку если объект одноэлементного множества ( ContentControl в данном случае) связан с представлением коллекции, он автоматически привязывается к CurrentItem представления.This works because when a singleton object (the ContentControl in this case) is bound to a collection view, it automatically binds to the CurrentItem of the view. Обратите внимание, что CollectionViewSource объекты автоматически синхронизировать денежного формата и выделение.Note that CollectionViewSource objects automatically synchronize currency and selection. Если элемент управления списка не привязан к CollectionViewSource объект как в этом примере, то необходимо задать его IsSynchronizedWithCurrentItem свойства true для правильной работы.If your list control is not bound to a CollectionViewSource object as in this example, then you would need to set its IsSynchronizedWithCurrentItem property to true for this to work.

Другие примеры см. в разделах Практическое руководство. Привязка к коллекции и вывод сведений в зависимости от выделенного элемента и Практическое руководство. Использование шаблона "главный — подчиненный" с иерархическими данными.For other examples, see Bind to a Collection and Display Information Based on Selection and Use the Master-Detail Pattern with Hierarchical Data.

Можно заметить, что в приведенном выше примере используется шаблон.You may have noticed that the above example uses a template. На самом деле, данные не будут отображаться выбранным способом без использования шаблонов (один явно используется элементом ContentControl и неявно используется ListBox).In fact, the data would not be displayed the way we wish without the use of templates (the one explicitly used by the ContentControl and the one implicitly used by the ListBox). К шаблонам данных мы перейдем в следующем разделе.We now turn to data templating in the next section.

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

Без использования шаблонов данных ИПUI приложения в подразделе Понятие привязки данных будет выглядеть следующим образом.Without the use of data templates, our application ИПUI in the What Is Data Binding? section would look like the following:

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

Как показано в примере в предыдущем разделе, как ListBox управления и ContentControl привязаны к всему объекту коллекции (или точнее, представление объекта коллекции) из AuctionItems.As shown in the example in the previous section, both the ListBox control and the ContentControl are bound to the entire collection object (or more specifically, the view over the collection object) of AuctionItems. Отсутствии особых инструкций по способу отображения сбора данных ListBox отображает строковое представление каждого объекта в базовой коллекции и ContentControl отображает строковое представление объекта, он связан.Without specific instructions of how to display the data collection, the ListBox is displaying a string representation of each object in the underlying collection and the ContentControl is displaying a string representation of the object it is bound to.

Чтобы решить эту проблему, приложение определяет DataTemplates.To solve that problem, the application defines DataTemplates. Как показано в примере в предыдущем разделе, ContentControl явным образом использует detailsProductListingTemplateDataTemplate.As shown in the example in the previous section, the ContentControl explicitly uses the detailsProductListingTemplateDataTemplate. ListBox Управления неявно использует следующий DataTemplate при отображении AuctionItem объектов в коллекции:The ListBox control implicitly uses the following DataTemplate when displaying the AuctionItem objects in the collection:

<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, результирующий пользовательский Интерфейс имеет, описанной в новые возможности привязки данных? раздел.With the use of those two DataTemplates, the resulting UI is the one shown in the What Is Data Binding? section. Как видно из этого снимка, в дополнение к возможности размещать данные в элементах управления, DataTemplates позволяют определять подходящие визуальные элементы для данных.As you can see from that screenshot, in addition to letting you place data in your controls, DataTemplates allow you to define compelling visuals for your data. Например DataTriggers используются выше DataTemplate таким образом, чтобы AuctionItems с SpecialFeatures значение выделите отображались с Оранжевые границы и помечается звездочкой.For example, DataTriggers are used in the above DataTemplate so that AuctionItems with SpecialFeatures value of HighLight would be displayed with an orange border and a star.

Дополнительные сведения о шаблонах данных см. в разделе Общие сведения о шаблонах данных.For more information about data templates, see the Data Templating Overview.

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

Для большинства приложений, принимающих входные данные от пользователя, необходима логика проверки, чтобы убедиться, что пользователь ввел ожидаемые данные.Most applications that take user input need to have validation logic to ensure that the user has entered the expected information. Проверка может основываться на типе, диапазоне, формате или других требованиях конкретного приложения.The validation checks can be based on type, range, format, or other application-specific requirements. В этом разделе рассматривается, как работает проверка данных в WPFWPF.This section discusses how data validation works in the WPFWPF.

Связь правил проверки и привязкиAssociating Validation Rules with a Binding

WPFWPF Модель привязки данных, вы сможете связать ValidationRules с вашей Binding объекта.The WPFWPF data binding model allows you to associate ValidationRules with your Binding object. Например, следующий пример связывает TextBox к свойству с именем StartPrice и добавляет ExceptionValidationRule объект Binding.ValidationRules свойство.For example, the following example binds a TextBox to a property named StartPrice and adds a ExceptionValidationRule object to the Binding.ValidationRules property.

<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 объект проверяет, является ли допустимым значение свойства.A ValidationRule object checks whether the value of a property is valid. WPFWPF имеются следующие два встроенных ValidationRule объектов:has the following two types of built-in ValidationRule objects:

  • Объект ExceptionValidationRule проверяет исключения, возникшие во время обновления свойства источника привязки.A ExceptionValidationRule checks for exceptions thrown during the update of the binding source property. В предыдущем примере StartPrice имеет тип integer.In the previous example, StartPrice is of type integer. Когда пользователь вводит значение, которое невозможно преобразовать в целое число, создается исключение, приводящее к тому, что привязка будет помечена как недопустимая.When the user enters a value that cannot be converted to an integer, an exception is thrown, causing the binding to be marked as invalid. Альтернативный синтаксис параметра ExceptionValidationRule явным образом заключается в задании ValidatesOnExceptions свойства true на вашей Binding или MultiBinding объекта.An alternative syntax to setting the ExceptionValidationRule explicitly is to set the ValidatesOnExceptions property to true on your Binding or MultiBinding object.

  • Объект DataErrorValidationRule выполняет проверку ошибок, вызываемых объектами, реализующими IDataErrorInfo интерфейс.A DataErrorValidationRule object checks for errors that are raised by objects that implement the IDataErrorInfo interface. Пример использования этого правила проверки, см. в разделе DataErrorValidationRule.For an example of using this validation rule, see DataErrorValidationRule. Альтернативный синтаксис параметра DataErrorValidationRule явным образом заключается в задании ValidatesOnDataErrors свойства true на вашей Binding или MultiBinding объекта.An alternative syntax to setting the DataErrorValidationRule explicitly is to set the ValidatesOnDataErrors property to true on your Binding or MultiBinding object.

Можно также создать свои собственные правила проверки путем наследования от ValidationRule класса и реализации Validate метод.You can also create your own validation rule by deriving from the ValidationRule class and implementing the Validate method. В следующем примере показано правило, используемое элементом Добавление списка продуктов «Дата начала» TextBox из новые возможности привязки данных? раздел:The following example shows the rule used by the Add Product Listing "Start Date" TextBox from the What Is Data Binding? section:

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;
        }
    }
}
Public Class FutureDateRule
    Inherits ValidationRule

    Public Overrides Function Validate(ByVal value As Object,
                                       ByVal cultureInfo As System.Globalization.CultureInfo) _
                                   As System.Windows.Controls.ValidationResult

        Dim DateVal As DateTime

        Try
            DateVal = DateTime.Parse(value.ToString)
        Catch ex As FormatException
            Return New ValidationResult(False, "Value is not a valid date.")
        End Try

        If DateTime.Now.Date > DateVal Then
            Return New ValidationResult(False, "Please enter a date in the future.")
        Else
            Return ValidationResult.ValidResult
        End If
    End Function
End Class

StartDateEntryForm TextBox использует этот FutureDateRule, как показано в следующем примере:The StartDateEntryForm TextBox uses this FutureDateRule, as shown in the following example:

<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 коллекцию при каждом нажатии клавиши.Note that because the UpdateSourceTrigger value is PropertyChanged, the binding engine updates the source value on every keystroke, which means it also checks every rule in the ValidationRules collection on every keystroke. Это будет обсуждаться далее в разделе "Процесс проверки".We discuss this further in the Validation Process section.

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

Если пользователь вводит недопустимое значение, можно сформировать отклик приложения ИПUI на ошибку.If the user enters an invalid value, you may want to provide some feedback about the error on the application ИПUI. Один из способов обеспечения такого отклика является установление Validation.ErrorTemplate присоединенное свойство пользовательского ControlTemplate.One way to provide such feedback is to set the Validation.ErrorTemplate attached property to a custom ControlTemplate. Как показано в предыдущем подразделе, StartDateEntryForm TextBox использует ErrorTemplate вызывается validationTemplate.As shown in the previous subsection, the StartDateEntryForm TextBox uses an ErrorTemplate called validationTemplate. В следующем примере показано определение элемента validationTemplate.The following example shows the definition of validationTemplate:

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

AdornedElementPlaceholder Элемент указывает, где должен размещаться элемент управления.The AdornedElementPlaceholder element specifies where the control being adorned should be placed.

Кроме того, можно также использовать ToolTip отображение сообщений об ошибках.In addition, you may also use a ToolTip to display the error message. Оба StartDateEntryForm и StartPriceEntryFormTextBoxиспользуют стиль textStyleTextBox, который создает ToolTip , Отображает сообщение об ошибке.Both the StartDateEntryForm and the StartPriceEntryFormTextBoxes use the style textStyleTextBox, which creates a ToolTip that displays the error message. В следующем примере показано определение элемента textStyleTextBox.The following example shows the definition of textStyleTextBox. Присоединенное свойство HasError является true когда один или несколько привязок к свойствам связанного элемента находятся в ошибки.The attached property HasError is true when one or more of the bindings on the properties of the bound element are in error.

<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, StartDateEntryForm TextBox при ошибке проверки выглядит следующим образом:With the custom ErrorTemplate and the ToolTip, the StartDateEntryForm TextBox looks like the following when there is a validation error:

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

Если ваш Binding имеет правила проверки, но вы не укажете ErrorTemplate на связанный элемент управления, по умолчанию ErrorTemplate будет использоваться для уведомления пользователей об ошибке проверки.If your Binding has associated validation rules but you do not specify an ErrorTemplate on the bound control, a default ErrorTemplate will be used to notify users when there is a validation error. Значение по умолчанию ErrorTemplate — это шаблон элемента управления, определяющий красную границу графического уровня.The default ErrorTemplate is a control template that defines a red border in the adorner layer. По умолчанию ErrorTemplate и ToolTip, ИПUI из StartPriceEntryForm TextBox при ошибке проверки выглядит следующим образом:With the default ErrorTemplate and the ToolTip, the ИПUI of the StartPriceEntryForm TextBox looks like the following when there is a validation error:

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

Пример предоставления логики проверки всех элементов управления в диалоговом окне см. в подразделе "Пользовательские диалоговые окна" раздела Общие сведения о диалоговых окнах.For an example of how to provide logic to validate all controls in a dialog box, see the Custom Dialog Boxes section in the Dialog Boxes Overview.

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

Проверка обычно выполняется, когда целевое значение передается свойству источника привязки.Validation usually occurs when the value of a target is transferred to the binding source property. Эта операция выполняется по TwoWay и OneWayToSource привязки.This occurs on TwoWay and OneWayToSource bindings. Таким образом, что причина обновления источника зависит от значения UpdateSourceTrigger свойства, как описано в разделе что инициирует обновления источника раздел.To reiterate, what causes a source update depends on the value of the UpdateSourceTrigger property, as described in the What Triggers Source Updates section.

Ниже описан процесс проверки.The following describes the validation process. Обратите внимание, что при возникновении ошибки проверки или ошибки другого типа на любом этапе данного процесса процесс будет прерван.Note that if a validation error or other type of error occurs at any time during this process, the process is halted.

  1. Обработчик привязки проверяет наличие пользовательских ValidationRule объекты, определенные, ValidationStep присваивается RawProposedValue для этого Binding, в этом случае он вызывает Validate метод на каждом ValidationRule пока не будет запущен один из них произошла ошибка или пока не будут выполнены все из них.The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to RawProposedValue for that Binding, in which case it calls the Validate method on each ValidationRule until one of them runs into an error or until all of them pass.

  2. Обработчик привязки вызывает преобразователь, если таковой существует.The binding engine then calls the converter, if one exists.

  3. При успешном завершении работы преобразователя обработчик привязки проверяет наличие пользовательских ValidationRule объекты, определенные, ValidationStep присваивается ConvertedProposedValue для этого Binding, в этом случае он вызывает Validate метод на каждом ValidationRule с ValidationStep присвоено ConvertedProposedValue пока не будет запущен один из них в ошибку или пока не будут выполнены все из них.If the converter succeeds, the binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to ConvertedProposedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to ConvertedProposedValue until one of them runs into an error or until all of them pass.

  4. Обработчик привязки присваивает значение исходному свойству.The binding engine sets the source property.

  5. Обработчик привязки проверяет наличие пользовательских ValidationRule объекты, определенные, ValidationStep присваивается UpdatedValue для этого Binding, в этом случае он вызывает Validate метод на каждом ValidationRule с ValidationStep значение UpdatedValue пока не будет запущен один из них в ошибку или пока не будут выполнены все из них.The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to UpdatedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to UpdatedValue until one of them runs into an error or until all of them pass. Если DataErrorValidationRule связан с привязкой и его ValidationStep имеет значение по умолчанию, UpdatedValue, DataErrorValidationRule установлен на этом этапе.If a DataErrorValidationRule is associated with a binding and its ValidationStep is set to the default, UpdatedValue, the DataErrorValidationRule is checked at this point. Это также является точкой при привязки, в которых ValidatesOnDataErrors присвоено true проверяются.This is also the point when bindings that have the ValidatesOnDataErrors set to true are checked.

  6. Обработчик привязки проверяет наличие пользовательских ValidationRule объекты, определенные, ValidationStep присваивается CommittedValue для этого Binding, в этом случае он вызывает Validate метод на каждом ValidationRule с ValidationStep значение CommittedValue пока не будет запущен один из них в ошибку или пока не будут выполнены все из них.The binding engine checks if there are any custom ValidationRule objects defined whose ValidationStep is set to CommittedValue for that Binding, in which case it calls the Validate method on each ValidationRule that has ValidationStep set to CommittedValue until one of them runs into an error or until all of them pass.

Если ValidationRule не передает в любое время, во время этого процесса, обработчик привязки создает ValidationError и добавляет его к Errors коллекции привязанного элемента.If a ValidationRule does not pass at any time throughout this process, the binding engine creates a ValidationError object and adds it to the Errors collection of the bound element. Перед привязкой запускается ядро ValidationRule объектов на любом этапе, удаляет все ValidationError , добавленный Errors присоединенное свойство привязанного элемента во время выполнения этого шага.Before the binding engine runs the ValidationRule objects at any given step, it removes any ValidationError that was added to the Errors attached property of the bound element during that step. Например если ValidationRule которого ValidationStep присваивается UpdatedValue сбой, в следующий раз, происходит процесс проверки, обработчик привязки удалит ValidationError непосредственно перед вызовом любого ValidationRule с ValidationStep значение UpdatedValue.For example, if a ValidationRule whose ValidationStep is set to UpdatedValue failed, the next time the validation process occurs, the binding engine removes that ValidationError immediately before it calls any ValidationRule that has ValidationStep set to UpdatedValue.

Когда Errors не является пустым, HasError присоединенное свойство элемента имеет значение true.When Errors is not empty, the HasError attached property of the element is set to true. Кроме того Если NotifyOnValidationError свойство Binding присваивается true, то обработчик привязки вызывает Validation.Error присоединенного события в элементе.Also, if the NotifyOnValidationError property of the Binding is set to true, then the binding engine raises the Validation.Error attached event on the element.

Также Обратите внимание, что при передаче допустимого значения в любом направлении (от целевого объекта к источнику и от источника к целевому объекту) очищается Errors вложенного свойства зависимостей.Also note that a valid value transfer in either direction (target to source or source to target) clears the Errors attached property.

Если привязки задано ExceptionValidationRule связанные с ней, или было ValidatesOnExceptions свойству true и создается исключение при обработчик привязки задает источник, обработчик привязки проверяет наличие UpdateSourceExceptionFilter.If the binding either has an ExceptionValidationRule associated with it, or had the ValidatesOnExceptions property is set to true and an exception is thrown when the binding engine sets the source, the binding engine checks to see if there is a UpdateSourceExceptionFilter. У вас есть возможность использовать UpdateSourceExceptionFilter обратного вызова, чтобы предоставить пользовательский обработчик для обработки исключений.You have the option to use the UpdateSourceExceptionFilter callback to provide a custom handler for handling exceptions. Если UpdateSourceExceptionFilter не указан в Binding, обработчик привязки создает ValidationError с исключением и добавляет ее к Errors коллекции привязанного элемента.If an UpdateSourceExceptionFilter is not specified on the Binding, the binding engine creates a ValidationError with the exception and adds it to the Errors collection of the bound element.

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

Можно задать присоединенное свойство TraceLevel связанные с привязкой объекта для получения сведений о состоянии конкретной привязки.You can set the attached property TraceLevel on a binding-related object to receive information about the status of a specific binding.

См. такжеSee also