Freigeben über


Binden von Daten an Steuerelemente (WCF Data Services)

Mit WCF Data Services können Sie Steuerelemente wie die Steuerelemente ComboBox und ListView an eine Instanz der DataServiceCollection<T>-Klasse binden. Diese Auflistung, die von der ObservableCollection<T>-Klasse übernommen wird, enthält die Daten aus einem Open Data Protocol (OData)-Feed. Die Klasse stellt eine dynamische Datensammlung dar, die Benachrichtigungen bereitstellt, wenn Elemente hinzugefügt oder entfernt werden. Wenn Sie eine Instanz der DataServiceCollection<T> für die Datenbindung verwenden, behandeln die WCF Data Services-Clientbibliotheken diese Ereignisse, um sicherzustellen, dass vom DataServiceContext verfolgte Objekte mit den Daten im gebundenen Benutzeroberflächenelement synchronisiert bleiben.

Die DataServiceCollection<T>-Klasse implementiert (indirekt) die INotifyCollectionChanged-Schnittstelle, um den Kontext zu warnen, wenn Objekte der Sammlung hinzugefügt oder daraus entfernt werden. Mit einer DataServiceCollection<T>-Instanz verwendete Datendiensttypobjekte müssen auch die INotifyPropertyChanged-Schnittstelle implementieren, um die DataServiceCollection<T>-Instanz zu warnen, wenn sich Eigenschaften von Objekten in der Bindungssammlung geändert haben.

Hinweis

Wenn Sie das Dialogfeld Dienstverweis hinzufügen oder das Tool DataSvcUtil.exe mit der /dataservicecollection-Option zum Generieren der Clientdatendienstklassen verwenden, implementieren die generierten Datenklassen die INotifyPropertyChanged-Schnittstelle.Weitere Informationen finden Sie unter Gewusst wie: Manuelles Generieren von Clientdatendienstklassen (WCF Data Services).

Erstellen der Bindungsauflistung

Erstellen Sie eine neue Instanz der DataServiceCollection<T>-Klasse, indem Sie eine der Klassenkonstruktormethoden mit einer angegebenen DataServiceContext-Instanz und optional eine DataServiceQuery<TElement> oder LINQ-Abfrage aufrufen, die bei Ausführung eine IEnumerable<T>-Instanz zurückgibt. Diese IEnumerable<T> stellt die Quelle von Objekten für die Bindungsauflistung bereit, die aus einem OData-Feed materialisiert werden. Weitere Informationen finden Sie unter Objektmaterialisierung (WCF Data Services). Standardmäßig werden an in die Auflistung eingefügten gebundenen Objekten und Elementen vorgenommene Änderungen automatisch vom DataServiceContext nachverfolgt. Wenn Sie diese Änderungen manuell nachverfolgen müssen, rufen Sie eine der Konstruktormethoden auf, die einen trackingMode-Parameter akzeptiert, und geben Sie einen Wert von None an.

Im folgenden Beispiel wird gezeigt, wie eine Instanz von DataServiceCollection<T> basierend auf einem angegebenen DataServiceContext und einer DataServiceQuery<TElement> erstellt wird, die alle Kunden mit verknüpften Bestellungen zurückgibt:

' 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"));

Binden von Daten an Windows Presentation Foundation-Elemente

Da die DataServiceCollection<T>-Klasse von der ObservableCollection<T>-Klasse erbt, können Sie Objekte in einer WPF (Windows Presentation Foundation)-Anwendung an ein Element oder Steuerelement binden, ähnlich wie beim Verwenden der ObservableCollection<T>-Klasse für die Bindung. Weitere Informationen finden Sie unter Data Binding (Windows Presentation Foundation) (in englischer Sprache). Eine Möglichkeit zum Binden von Datendienstdaten an WPF-Steuerelemente ist das Festlegen der DataContext-Eigenschaft des Elements auf die Instanz der DataServiceCollection<T>-Klasse, die das Abfrageergebnis enthält. In diesem Fall verwenden Sie die ItemsSource-Eigenschaft, um die Objektquelle für das Steuerelement festzulegen. Verwenden Sie die DisplayMemberPath-Eigenschaft, um anzugeben, welche Eigenschaft des gebundenen Objekts angezeigt werden soll. Wenn Sie ein Element an ein verknüpftes Objekt binden, das von einer Navigationseigenschaft zurückgegeben wird, schließen Sie den Pfad in die für die ItemsSource-Eigenschaft definierte Bindung ein. Der Pfad ist relativ zum Stammobjekt, das von der DataContext-Eigenschaft des übergeordneten Steuerelements festgelegt ist. Im folgenden Beispiel wird die DataContext-Eigenschaft eines StackPanel-Elements festgelegt, um das übergeordnete Steuerelement an eine DataServiceCollection<T> von Customer-Objekten zu binden:

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

    ' 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.
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 Customers)(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
    Me.LayoutRoot.UpdateLayout()
' 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;
// 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);

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

Das folgende Beispiel veranschaulicht die XAML-Bindungsdefinition des untergeordneten DataGrid-Elements und der ComboBox-Steuerelemente:

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

Weitere Informationen finden Sie unter Gewusst wie: Binden von Daten an Windows Presentation Foundation-Elemente (WCF Data Services).

Wenn eine Entität an einer 1:n- oder m:n-Beziehung beteiligt ist, gibt die Navigationseigenschaft für die Beziehung eine Auflistung von verknüpften Objekten zurück. Wenn Sie das Dialogfeld Dienstverweis hinzufügen oder das Tool DataSvcUtil.exe zum Generieren der Clientdatendienstklassen verwenden, gibt die Navigationseigenschaft eine Instanz von DataServiceCollection<T> zurück. Dies ermöglicht es Ihnen, verknüpfte Objekte an ein Steuerelement zu binden, und unterstützt allgemeine WPF-Bindungsszenarien, z. B. das Master-Detail-Bindungsmuster für verknüpfte Entitäten. Im vorherigen XAML-Beispiel bindet der XAML-Code die Master-DataServiceCollection<T> an das Stammdatenelement. Die Bestellung DataGrid wird dann an die aus dem ausgewählten Customers-Objekt zurückgegebene Orders-DataServiceCollection<T> gebunden, die wiederum an das Stammdatenelement des Window gebunden wird.

Binden von Daten an Windows Forms-Steuerelemente

Legen Sie die DataSource-Eigenschaft des Steuerelements auf die Instanz der DataServiceCollection<T>-Klasse fest, die das Abfrageergebnis enthält, um Objekte an ein Windows Form-Steuerelement zu binden.

Hinweis

Die Datenbindung wird nur für Steuerelemente unterstützt, die Änderungsereignisse durch das Implementieren der INotifyCollectionChanged- und der INotifyPropertyChanged-Schnittstelle überwachen.Wenn ein Steuerelement diese Art von Änderungsbenachrichtigung nicht unterstützt, spiegeln sich Änderungen, die an der zugrunde liegenden DataServiceCollection<T> vorgenommen werden, nicht im gebundenen Steuerelement wider.

Im folgenden Beispiel wird eine DataServiceCollection<T> an ein ComboBox-Steuerelement gebunden:

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

Wenn Sie das Dialogfeld Dienstverweis hinzufügen zum Generieren der Clientdatendienstklassen verwenden, wird auch eine Projektdatenquelle erstellt, die auf dem generierten DataServiceContext basiert. Mit dieser Datenquelle können Sie Benutzeroberflächenelemente oder Steuerelemente erstellen, die Daten aus dem Datendienst einfach durch Ziehen von Elementen aus dem Fenster Datenquellen auf den Designer anzeigen. Diese Elemente werden zu an die Datenquelle gebundenen Elementen auf der Benutzeroberfläche der Anwendung. Weitere Informationen finden Sie unter Vorgehensweise: Binden von Daten mit einer Projektdatenquelle (WCF Data Services).

Binden von ausgelagerten Daten

Ein Datendienst kann so konfiguriert werden, dass die Menge an abgefragten Daten beschränkt wird, die in einer einzelnen Antwortnachricht zurückgegeben werden. Weitere Informationen finden Sie unter Konfigurieren des Datendiensts (WCF Data Services). Wenn der Datendienst Paging von Antwortdaten durchführt, enthält jede Antwort einen Link, der zum Zurückgeben der nächsten Ergebnisseite verwendet wird. Weitere Informationen finden Sie unter Laden von verzögertem Inhalt (WCF Data Services). In diesem Fall müssen Sie Seiten durch Aufrufen der Load-Methode für die DataServiceCollection<T> explizit laden, indem Sie den aus der NextLinkUri-Eigenschaft abgerufenen URI wie im folgenden Beispiel weiterleiten:

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

Verknüpfte Objekte werden auf ähnliche Weise geladen. Weitere Informationen finden Sie unter Gewusst wie: Binden von Daten an Windows Presentation Foundation-Elemente (WCF Data Services).

Anpassen von Datenbindungsverhalten

Die DataServiceCollection<T>-Klasse ermöglicht Ihnen das Abfangen der Ereignisse, die ausgelöst werden, wenn Änderungen an der Auflistung wie das Hinzufügen oder Entfernen eines Objekts und wenn Änderungen an den Eigenschaften des Objekts in einer Auflistung vorgenommen werden. Sie können die Datenbindungsereignisse ändern, um das Standardverhalten zu überschreiben, was die folgenden Einschränkungen einschließt:

  • Innerhalb der Delegaten wird keine Validierung ausgeführt.

  • Beim Hinzufügen einer Entität werden automatisch verknüpfte Entitäten hinzugefügt.

  • Beim Löschen einer Entität werden die verknüpften Entitäten nicht gelöscht.

Wenn Sie eine neue Instanz der DataServiceCollection<T> erstellen, haben Sie die Option, die folgenden Parameter anzugeben, die Delegaten für Methoden definieren, die die beim Ändern gebundener Objekte ausgelösten Ereignisse behandeln:

Hinweis

WCF Data Services überprüft die benutzerdefinierten Verhalten nicht, die Sie in diesen Delegaten implementieren.

Im folgenden Beispiel wird die Remove-Aktion angepasst, um die DeleteLink-Methode und DeleteObject-Methode zum Entfernen von Orders_Details-Entitäten aufzurufen, die zu einer gelöschten Orders-Entität gehören. Diese benutzerdefinierte Aktion wird ausgeführt, da abhängige Entitäten beim Löschen der übergeordneten Entität nicht automatisch gelöscht werden.

' 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(Orders) Then

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

            ' Load the related OrderDetails.
            context.LoadProperty(deletedOrder, "Order_Details")

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

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

            Return False
        Else
            Return True
        End If
    Else
        ' Use the default behavior.
        Return True
    End If
End Function
' 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;
    }
}

Weitere Informationen finden Sie unter Gewusst wie: Anpassen des Datenbindungsverhaltens (WCF Data Services).

Das Standardverhalten beim Entfernen eines Objekts aus einer DataServiceCollection<T> mit der Remove-Methode ist, dass das Objekt auch im DataServiceContext als gelöscht markiert wird. Sie können einen Delegaten für eine Methode im entityCollectionChanged-Parameter angeben, der beim Auftreten des CollectionChanged-Ereignisses aufgerufen wird, um dieses Verhalten zu ändern.

Datenbindung mit benutzerdefinierten Clientdatenklassen

Um Objekte in eine DataServiceCollection<T> laden zu können, müssen die Objekte selbst die INotifyPropertyChanged-Schnittstelle implementieren. Beim Verwenden des Dialogfelds Dienstverweis hinzufügen oder des Tools DataSvcUtil.exe generierte Datendienstclientklassen implementieren diese Schnittstelle. Wenn Sie eigene Clientdatenklassen bereitstellen, müssen Sie einen anderen Auflistungstyp für die Datenbindung verwenden. Wenn sich Objekte ändern, müssen Sie Ereignisse in den datengebundenen Steuerelementen behandeln, um die folgenden Methoden der DataServiceContext-Klasse aufzurufen:

  • AddObject - wenn der Auflistung ein neues Objekt hinzugefügt wird.

  • DeleteObject - wenn ein Objekt aus der Auflistung entfernt wird.

  • UpdateObject - wenn die Eigenschaft eines Objekts in der Auflistung geändert wird.

  • AddLink - wenn einer Auflistung des verknüpften Objekts ein Objekt hinzugefügt wird.

  • SetLink - wenn einer Auflistung verknüpfter Objekte ein Objekt hinzugefügt wird.

Weitere Informationen finden Sie unter Aktualisieren des Datendiensts WCF Data Services.

Siehe auch

Aufgaben

Gewusst wie: Manuelles Generieren von Clientdatendienstklassen (WCF Data Services)

Gewusst wie: Hinzufügen eines Datendienstverweises (WCF Data Services)