Поделиться через


Привязка данных к элементам управления (службы WCF Data Services)

С помощью служб Службы WCF Data Services можно привязывать элементы управления, такие как ComboBox и ListView, к экземпляру класса DataServiceCollection. Эта коллекция, наследуемая от класса ObservableCollection, содержит данные из канала Протокол Open Data Protocol (OData) . Этот класс представляет коллекцию динамических данных, обеспечивающих выдачу уведомлений при добавлении и удалении элементов. При использовании экземпляра DataServiceCollection для привязки данных клиентские библиотеки Службы WCF Data Services обрабатывают эти события, обеспечивая синхронизацию объектов, отслеживаемых контекстом DataServiceContext, с данными в привязанном элементе пользовательского интерфейса.

Класс DataServiceCollection реализует интерфейс INotifyCollectionChanged (не напрямую) для оповещения контекста о добавлении и удалении объектов в коллекции. Объекты типа службы данных, используемые с коллекцией DataServiceCollection, должны также реализовать интерфейс INotifyPropertyChanged для оповещения объекта DataServiceCollection об изменении свойств объектов в привязанной коллекции.

Ee373844.note(ru-ru,VS.100).gifПримечание
При использовании диалога Добавление ссылки на службу или программыDataSvcUtil.exe с параметром /dataservicecollection для формирования клиентских классов службы данных сформированные классы данных реализуют интерфейс INotifyPropertyChanged.Дополнительные сведения см. в разделе Как формировать клиентские классы службы данных вручную (службы WCF Data Services).

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

Создать новый экземпляр класса DataServiceCollection можно путем вызова одного из конструкторов класса, передав ему экземпляр DataServiceContext и необязательный объект DataServiceQuery или запрос LINQ, при выполнении которого возвращается экземпляр IEnumerable. Этот объект IEnumerable представляет собой источник объектов для коллекции привязок, материализуемых из канала OData . Дополнительные сведения см. в разделе Материализация объектов (службы WCF Data Services). По умолчанию изменения в привязанных объектах и элементах, вставляемых в коллекцию, автоматически отслеживаются контекстом DataServiceContext. Для отслеживания изменений вручную можно вызвать один из конструкторов, принимающих параметр trackingMode, и указать значение None.

Следующий пример иллюстрирует создание экземпляра DataServiceCollection на основе переданного контекста DataServiceContext и объекта DataServiceQuery, который возвращает всех клиентов вместе со связанными с ними заказами.

' Create a new collection that contains all customers and related orders.
Dim trackedCustomers As DataServiceCollection(Of Customer) = _
        New DataServiceCollection(Of Customer)(context.Customers.Expand("Orders"))
// Create a new collection that contains all customers and related orders.
DataServiceCollection<Customer> trackedCustomers = 
    new DataServiceCollection<Customer>(context.Customers.Expand("Orders"));

Привязка данных к элементам Windows Presentation Foundation

Поскольку класс DataServiceCollection является наследником класса ObservableCollection, привязывать объекты к компоненту или элементу управления в приложении Windows Presentation Foundation (WPF) можно так же, как и при использовании для привязки класса ObservableCollection. Дополнительные сведения см. в разделе Привязка данных (Windows Presentation Foundation). Одним из способов привязки данных службы данных к элементам управления WPF является задание значения свойства DataContext элемента, равного экземпляру класса DataServiceCollection, который содержит результат выполнения запроса. В этом случае используйте свойство ItemsSource для задания источника объектов для элемента управления. Используйте свойство DisplayMemberPath для задания отображаемого свойства привязанного объекта. Если элемент привязывается к связанному объекту, возвращаемому свойством навигации, включите путь в привязку, определенную для свойства ItemsSource. Данный путь задается относительно корневого объекта, заданного свойством DataContext родительского элемента управления. В следующем примере задается свойство DataContext элемента StackPanel для привязки родительского элемента управления к коллекции клиентских объектов DataServiceCollection.

' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
                        Where cust.Country = customerCountry _
                        Select cust

' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery, _
        TrackingMode.AutoChangeTracking, "Customers", _
        AddressOf OnMyPropertyChanged, AddressOf OnMyCollectionChanged)

' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers
// Create a LINQ query that returns customers with related orders.
var customerQuery = from cust in context.Customers.Expand("Orders")
                    where cust.Country == customerCountry
                    select cust;

// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery, 
    TrackingMode.AutoChangeTracking,"Customers", 
    OnPropertyChanged, OnCollectionChanged);

// Bind the root StackPanel element to the collection;
// related object binding paths are defined in the XAML.
this.LayoutRoot.DataContext = trackedCustomers;

В следующем примере показано определение привязки XAML для дочерних элементов управления DataGrid и ComboBox:

<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
    <Label Content="Customer ID" Margin="20,0,0,0" />
    <ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}" 
              IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120" 
              HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
    <ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
        <ListView.View>
            <GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
                <GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}" 
                    Header="Order ID" Width="50"/>
                <GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}" 
                    Header="Order Date" Width="50"/>
                <GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}" 
                    Header="Freight Cost" Width="50"/>
            </GridView>
        </ListView.View>
    </ListView>
    <Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click" 
            Width="80" Height="30" Margin="450,0,0,0"/>
</StackPanel>

Дополнительные сведения см. в разделе Как привязать данные к элементам Windows Presentation Foundation (службы WCF Data Services).

Если сущность участвует в отношении «один ко многим» или «многие ко многим», свойство навигации отношения возвращает коллекцию связанных объектов. При использовании диалогового окна Добавление ссылки на службу или программы DataSvcUtil.exe для формирования клиентских классов службы данных свойство навигации возвращает экземпляр DataServiceCollection. Это позволяет привязывать связанные объекты к элементу управления с поддержкой типовых сценариев привязки WPF, таких как шаблон привязки «основной-подробности» для связанных сущностей. В предыдущем примере XAML код XAML привязывает основную коллекцию DataServiceCollection к корневому элементу данных. Затем заказ DataGrid привязывается к коллекции объектов Orders DataServiceCollection, возвращаемой для выбранного объекта Customers, который в свою очередь привязывается к корневому элементу данных объекта Window.

Привязка данных к элементам управления Windows Forms

Для привязки объектов к элементу управления Windows Form задайте значение свойства DataSource элемента управления, равное экземпляру класса DataServiceCollection, который содержит результат выполнения запроса.

Ee373844.note(ru-ru,VS.100).gifПримечание
Привязка данных поддерживается только для элементов управления, прослушивающих события изменений путем реализации интерфейсов INotifyCollectionChanged и INotifyPropertyChanged.Если элемент управления не поддерживает этот тип уведомлений об изменениях, изменения в базовом объекте DataServiceCollection не отражаются в привязанном элементе управления.

В следующем примере показана привязка коллекции DataServiceCollection к элементу управления ComboBox:

' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)

'Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID"
customersComboBox.DataSource = trackedCustomers
// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery);

//Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID";
customersComboBox.DataSource = trackedCustomers;

При использовании диалога Добавление ссылки на службу для формирования клиентских классов службы данных также создается источник данных проекта на основе сформированного контекста DataServiceContext. Этот источник данных позволяет создавать компоненты и элементы управления пользовательского интерфейса, отображающие данные службы данных путем простого перетаскивания элементов из окна Источники данных на окно конструктора. Добавленные элементы становятся элементами пользовательского интерфейса приложения, привязанными к источнику данных. Дополнительные сведения см. в разделе Как привязать данные с помощью источника данных проекта (службы данных WCF Data Services).

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

Служба данных может быть настроена для ограничения объема запрашиваемых данных, возвращаемых в отдельном ответном сообщении. Дополнительные сведения см. в разделе Настройка службы данных (службы WCF Data Services). Если служба данных использует подкачку страниц для возврата запрашиваемых данных, в каждом ответе содержится ссылка, используемая для возврата следующей страницы результатов. Дополнительные сведения см. в разделе Загрузка отложенного содержимого (службы WCF Data Services). В этом случае необходимо явно загружать страницы путем вызова метода Load объекта DataServiceCollection, передавая ему URI, полученный из свойства NextLinkUri, как показано в следующем примере.

    ' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)

    ' Load all pages of the response at once.
While trackedCustomers.Continuation IsNot Nothing
    trackedCustomers.Load( _
            context.Execute(Of Customer)(trackedCustomers.Continuation.NextLinkUri))
End While
// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery);

// Load all pages of the response at once.
while (trackedCustomers.Continuation != null)
{
    trackedCustomers.Load(
        context.Execute<Customer>(trackedCustomers.Continuation.NextLinkUri));
}

Связанные объекты загружаются аналогичным способом. Дополнительные сведения см. в разделе Как привязать данные к элементам Windows Presentation Foundation (службы WCF Data Services).

Настройка поведения привязки данных

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

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

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

  • При удалении сущности связанные сущности не удаляются.

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

  • entityChanged — метод, вызываемый при изменении свойства привязанного объекта. Делегат Func принимает объект EntityChangedParams и возвращает логическое значение, указывающее, должно ли по-прежнему применяться поведение по умолчанию, то есть вызов метода UpdateObject контекста DataServiceContext.

  • entityCollectionChanged — метод, вызываемый при добавлении или удалении объекта из коллекции привязок. Делегат Func принимает объект EntityCollectionChangedParams и возвращает логическое значение, указывающее, должно ли по-прежнему применяться поведение по умолчанию, то есть вызов метода AddObject для действия Add или метода DeleteObject для действия Remove применительно к контексту DataServiceContext.

Ee373844.note(ru-ru,VS.100).gifПримечание
Службы Службы WCF Data Services не выполняют никаких проверок специализированного поведения, реализованного в этих делегатах.

В следующем примере задано специализированное действие Remove, вызывающее метод DeleteLink и DeleteObject для удаления сущностей Orders_Details, принадлежащих удаленной сущности Orders. Это специализированное действие выполняется, поскольку зависимые сущности не удаляются автоматически при удалении родительской сущности.

' Method that is called when the CollectionChanged event is handled.
Private Function OnMyCollectionChanged( _
    ByVal entityCollectionChangedinfo As EntityCollectionChangedParams) As Boolean
    If entityCollectionChangedinfo.Action = _
        NotifyCollectionChangedAction.Remove Then

        ' Delete the related items when an order is deleted.
        If entityCollectionChangedinfo.TargetEntity.GetType() Is GetType(Order) Then

            ' Get the context and object from the supplied parameter.
            Dim context = entityCollectionChangedinfo.Context
            Dim deletedOrder As Order = _
            CType(entityCollectionChangedinfo.TargetEntity, Order)

            If deletedOrder.Order_Details.Count = 0 Then
                ' Load the related OrderDetails.
                context.LoadProperty(deletedOrder, "Order_Details")
            End If

            ' Delete the order and its related items
            For Each item As Order_Detail In deletedOrder.Order_Details
                context.DeleteObject(item)
            Next

            ' Delete the order and then return false since the object is already deleted.
            context.DeleteObject(deletedOrder)

            Return True
        Else
            Return False
        End If
    Else
        ' Use the default behavior.
        Return False
    End If
End Function
// Method that is called when the CollectionChanged event is handled.
private bool OnCollectionChanged(
    EntityCollectionChangedParams entityCollectionChangedinfo)
{
    if (entityCollectionChangedinfo.Action ==
        NotifyCollectionChangedAction.Remove)
    {
        // Delete the related items when an order is deleted.
        if (entityCollectionChangedinfo.TargetEntity.GetType() == typeof(Order))
        {
            // Get the context and object from the supplied parameter.
            DataServiceContext context = entityCollectionChangedinfo.Context;
            Order deletedOrder = entityCollectionChangedinfo.TargetEntity as Order;

            if (deletedOrder.Order_Details.Count == 0)
            {
                // Load the related OrderDetails.
                context.LoadProperty(deletedOrder, "Order_Details");
            }

            // Delete the order and its related items;
            foreach (Order_Detail item in deletedOrder.Order_Details)
            {
                context.DeleteObject(item);
            }

            // Delete the order and then return true since the object is already deleted.
            context.DeleteObject(deletedOrder);

            return true;
        }
        else
        {
            return false;
        }
    }
    else 
    {
        // Use the default behavior.
        return false;
    }
}

Дополнительные сведения см. в разделе Как настроить режим привязки данных (службы WCF Data Services).

Поведение по умолчанию при удалении объекта из коллекции DataServiceCollection с помощью метода Remove состоит в том, что объект также помечается как удаленный в контексте DataServiceContext. Для изменения этого поведения можно задать в параметре entityCollectionChanged делегат метода, который будет вызываться при возникновении события CollectionChanged.

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

Для загрузки объектов в коллекцию DataServiceCollection эти объекты сами должны реализовывать интерфейс INotifyPropertyChanged. Клиентские классы службы данных, формируемые при использовании диалогового окна Добавление ссылки на службу или программыDataSvcUtil.exe, реализуют данный интерфейс. При предоставлении собственных клиентских классов данных необходимо использовать другой тип коллекции для привязки данных. При изменении объектов необходимо обрабатывать события в элементах управления с привязанными данными для вызова следующих методов класса DataServiceContext.

  • AddObject — при добавлении в коллекцию нового объекта.

  • DeleteObject — при удалении объекта из коллекции.

  • UpdateObject — при изменении свойства объекта в коллекции.

  • AddLink — при добавлении объекта в коллекцию связанного объекта.

  • SetLink — при добавлении объекта в коллекцию связанных объектов.

Дополнительные сведения см. в разделе Обновление службы данных (службы WCF Data Services).

См. также

Задачи

Как формировать клиентские классы службы данных вручную (службы WCF Data Services)
Как добавить ссылку на службу данных (службы WCF Data Services)