Liaison des données aux contrôles (WCF Data Services)
Avec Services de données WCF, vous pouvez lier des contrôles tels que les contrôles ComboBox et ListView à une instance de la classe DataServiceCollection<T>. Cette collection, qui hérite de la classe ObservableCollection<T>, contient les données d'un flux Protocole OData (Open Data). Cette classe représente une collection de données dynamique qui fournit des notifications lorsque des éléments sont ajoutés ou supprimés. Lorsque vous utilisez une instance de DataServiceCollection<T> pour la liaison de données, les bibliothèques clientes Services de données WCF gèrent ces événements pour vérifier que les objets suivis par DataServiceContext restent synchronisés avec les données dans l'élément d'interface utilisateur relié.
La classe DataServiceCollection<T> implémente (indirectement) l'interface INotifyCollectionChanged pour alerter le contexte lorsque des objets sont ajoutés ou supprimés de la collection. Les objets de type de service de données utilisés avec DataServiceCollection<T> doivent également implémenter l'interface INotifyPropertyChanged pour alerter DataServiceCollection<T> lorsque les propriétés d'objets dans la collection de liaisons ont changé.
Notes
Lorsque vous utilisez la boîte de dialogue Ajouter une référence de service ou l'outil DataSvcUtil.exe avec l'option /dataservicecollection pour générer les classes de service de données client, les classes de données générées implémentent l'interface INotifyPropertyChanged.Pour plus d'informations, consultez Procédure : générer manuellement des classes de service de données client (WCF Data Services).
Création de la collection de liaisons
Créez une nouvelle instance de la classe DataServiceCollection<T> en appelant l'une des méthodes de constructeur de classe avec une instance DataServiceContext fournie et éventuellement une requête DataServiceQuery<TElement> ou LINQ qui, lorsqu'elle est exécutée, retourne une instance IEnumerable<T>. Cette instance IEnumerable<T> fournit la source d'objets pour la collection de liaisons, matérialisés à partir d'un flux OData. Pour plus d'informations, consultez Matérialisation d'objets (WCF Data Services). Par défaut, les modifications apportées aux objets liés et aux éléments insérés dans la collection sont suivies automatiquement par DataServiceContext. Si vous devez suivre ces modifications manuellement, appelez l'une des méthodes de constructeur qui prend un paramètre trackingMode et spécifiez une valeur None.
L'exemple suivant montre comment créer une instance de DataServiceCollection<T> à partir d'un DataServiceContext fourni et d'une DataServiceQuery<TElement> qui retourne tous les clients avec les ordres associés :
' 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"));
Liaison de données aux éléments Windows Presentation Foundation
Étant donné que la classe DataServiceCollection<T> hérite de la classe ObservableCollection<T>, vous pouvez lier des objets à un élément ou un contrôle dans une application WPF (Windows Presentation Foundation) comme vous le feriez lorsque vous utilisez la classe ObservableCollection<T> pour la liaison. Pour plus d'informations, consultez Liaison de données (Windows Presentation Foundation). Une façon de lier des données du service des données aux contrôles WPF est de définir la propriété DataContext de l'élément sur l'instance de la classe DataServiceCollection<T> qui contient le résultat de la requête. Dans ce cas, utilisez la propriété ItemsSource pour définir la source de l'objet pour le contrôle. Utilisez la propriété DisplayMemberPath pour spécifier quelle propriété de l'objet lié afficher. Si vous liez un élément à un objet connexe retourné par une propriété de navigation, incluez le chemin d'accès dans la liaison définie pour la propriété ItemsSource. Ce chemin d'accès est relatif à l'objet racine défini par la propriété DataContext du contrôle parent. L'exemple suivant définit la propriété DataContext d'un élément StackPanel pour qu'elle lie le contrôle parent à une DataServiceCollection<T> d'objets de client :
' 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;
L'exemple suivant montre la définition de la liaison XAML des contrôles enfants DataGrid et 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>
Pour plus d'informations, consultez Procédure : lier des données aux éléments Windows Presentation Foundation (WCF Data Services).
Lorsqu'une entité participe à une relation un-à-plusieurs ou plusieurs-à-plusieurs, la propriété de navigation de la relation retourne une collection d'objets connexes. Lorsque vous utilisez la boîte de dialogue Ajouter une référence de service ou l'outil DataSvcUtil.exe pour générer les classes de service de données client, la propriété de navigation retourne une instance de DataServiceCollection<T>. Cette opération vous permet de lier des objets connexes à un contrôle, et de prendre en charge des scénarios WPF courants, tels que le modèle de liaison maître/détail pour les entités connexes. Dans l'exemple de code XAML précédent, le code XAML lie le DataServiceCollection<T> principal à l'élément de données racine. Puis l'ordre DataGrid est lié aux Orders que DataServiceCollection<T> a retourné de l'objet Customers sélectionné qui à son tour est lié à l'élément des données racine de Window.
Liaison de données aux contrôles Windows Forms
Pour lier des objets à un contrôle Windows Form, définissez la propriété DataSource du contrôle sur l'instance de la classe DataServiceCollection<T> qui contient le résultat de la requête.
Notes
La liaison de données n'est prise en charge que pour le contrôle à l'écoute des événements de modification en implémentant les interfaces INotifyCollectionChanged et INotifyPropertyChanged.Lorsqu'un contrôle ne prend pas en charge ce type de notification des modifications, les modifications apportées à l'objet DataServiceCollection<T> sous-jacent ne sont pas répercutées sur le contrôle dépendant.
L'exemple suivant lie un objet DataServiceCollection<T> à un contrôle 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;
Lorsque vous utilisez la boîte de dialogue Ajouter une référence de service pour générer les classes de service de données client, une source de données projet est également créée qui est basée sur le DataServiceContext généré. Avec cette source de données, vous pouvez créer des éléments d'interface utilisateur ou des contrôles qui affichent des données issues du service de données en faisant simplement glisser des éléments de la fenêtre Sources de données sur le concepteur. Ces éléments deviennent des éléments dans l'interface utilisateur de l'application qui sont liés à la source de données. Pour plus d'informations, consultez Procédure : lier des données à l'aide d'une source de données projet (WCF Data Services).
Liaison de données paginées
Un service de données peut être configuré pour limiter la quantité de données interrogées qui sont retournées dans un message de réponse unique. Pour plus d'informations, consultez Configuration du service de données (WCF Data Services). Lorsque le service de données pagine des données de réponse, chaque réponse contient un lien utilisé pour retourner la page suivante de résultats. Pour plus d'informations, consultez Chargement de contenu différé (WCF Data Services). Dans ce cas, vous devez charger explicitement des pages en appelant la méthode Load sur DataServiceCollection<T> en passant l'URI obtenu de la propriété NextLinkUri, comme dans l'exemple suivant :
' 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));
}
Les objets connexes sont chargés de façon semblable. Pour plus d'informations, consultez Procédure : lier des données aux éléments Windows Presentation Foundation (WCF Data Services).
Personnalisation des comportements de liaison de données
La classe DataServiceCollection<T> vous permet d'intercepter les événements déclenchés lorsque des modifications sont apportées à la collection, telles que l'ajout ou la suppression d'un objet, et lorsque les modifications sont apportées aux propriétés d'objet dans une collection. Vous pouvez modifier les événements de liaison de données pour remplacer le comportement par défaut qui inclut les contraintes suivantes :
Aucune validation n'est effectuée dans les délégués.
L'ajout d'une entité ajoute automatiquement des entités connexes.
La suppression d'une entité ne supprime pas les entités connexes.
Lorsque vous créez une nouvelle instance de DataServiceCollection<T>, vous avez l'option de spécifier les paramètres suivants qui définissent des délégués aux méthodes qui gèrent les événements déclenchés lorsque les objets liés sont modifiés :
entityChanged - méthode appelée lors de la modification de la propriété d'un objet lié. Ce délégué Func<T, TResult> accepte un objet EntityChangedParams et retourne une valeur booléenne qui indique si le comportement par défaut, appeler UpdateObject sur le DataServiceContext, doit encore se produire.
entityCollectionChanged- méthode appelée lorsqu'un objet est ajouté ou supprimé de la collection de liaisons. Ce délégué Func<T, TResult> accepte un objet EntityCollectionChangedParams et retourne une valeur booléenne qui indique si le comportement par défaut, appeler AddObject pour une action Add ou DeleteObject pour une action Remove sur DataServiceContext, doit encore se produire.
Notes
Services de données WCF n'effectue aucune validation des comportements personnalisés que vous implémentez dans ces délégués.
Dans l'exemple suivant, l'action Remove est personnalisée pour appeler la méthode DeleteLink et DeleteObject pour supprimer des entités Orders_Details qui appartiennent à une entité Orders supprimée. Cette action personnalisée est effectuée parce que les entités dépendantes ne sont pas supprimées automatiquement lorsque l'entité parente est supprimée.
' 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;
}
}
Pour plus d'informations, consultez Procédure : personnaliser des comportements de liaison de données (WCF Data Services).
Le comportement par défaut lorsqu'un objet est supprimé d'une DataServiceCollection<T> à l'aide de la méthode Remove est que l'objet est également marqué comme supprimé dans DataServiceContext. Pour modifier ce comportement, vous pouvez spécifier un délégué à une méthode dans le paramètre entityCollectionChanged qui est appelé lorsque l'événement CollectionChanged se produit.
Liaison de données avec les classes de données de client personnalisées
Pour pouvoir charger des objets dans DataServiceCollection<T>, les objets eux-mêmes doivent implémenter l'interface INotifyPropertyChanged. Les classes clientes du service de données générées lorsque vous utilisez la boîte de dialogue Ajouter une référence de service ou l'outil DataSvcUtil.exe implémentent cette interface. Si vous fournissez vos propres classes de données clientes, vous devez utiliser un autre type de collection pour la liaison de données. Lorsque les objets changent, vous devez gérer des événements dans les contrôles liés aux données pour appeler les méthodes suivantes de la classe DataServiceContext :
AddObject- lorsqu'un nouvel objet est ajouté à la collection.
DeleteObject - lorsqu'un objet est supprimé de la collection.
UpdateObject- lorsqu'une propriété est modifiée sur un objet dans la collection.
AddLink- lorsqu'un objet est ajouté à une collection d'objets connexes.
SetLink- lorsqu'un objet est ajouté à une collection d'objets connexes.
Pour plus d'informations, consultez Mise à jour du service de données (WCF Data Services).
Voir aussi
Tâches
Procédure : générer manuellement des classes de service de données client (WCF Data Services)
Procédure : ajouter une référence de service de données (WCF Data Services)