Loading Related Entities (WCF Data Services/Silverlight)

In this task, you will extend the code from the previous task to also load Order_Details objects that are related to the selected Orders object. In the method that handles the SelectionChanged event, which is raised by the orders DataGrid, you call the BeginLoadProperty method on the DataServiceContext to asynchronously load Order_Details objects that are related to the Order object that is selected in the grid. These orders are added to an ObservableCollection<T> that is bound to a second data grid.

To load items that belong to a selected order

  1. Open the MainPage.xaml.cs source code file of the Silverlight project.

  2. In the public constructor method for the MainPage class, insert the following code that registers a handler for the SelectionChanged event on the OrdersDataGrid.

    ' Register a handler for the SelectionChanged event on the orders grid.
    AddHandler ordersGrid.SelectionChanged, AddressOf ordersGrid_SelectionChanged
    
    // Register a handler for the SelectionChanged event on the orders grid.
    ordersGrid.SelectionChanged +=
        new SelectionChangedEventHandler(ordersGrid_SelectionChanged);
    
  3. Add the following methods to the MainPage class. These methods are called when an order is selected in the ordersGrid. The LoadDetails method calls the BeginLoadProperty method on the context to load Order_Details objects that are related the currently selected Orders object. The OnOrderDetailsLoaded method handles the result of this asynchronous operation by calling EndLoadProperty and adding the returned Order_Details objects into an ObservableCollection<T> that is bound to a second DataGrid.

    Private Sub ordersGrid_SelectionChanged(ByVal sender As Object, _
                                            ByVal e As SelectionChangedEventArgs)
        ' Set the current order.
        currentOrder = CType(ordersGrid.SelectedItem, Order)
    
        ' Clear the message text.
        messageTextBlock.Text = String.Empty
    
        ' Load details for the selected order.
        LoadDetails(currentOrder)
    
    End Sub
    Private Sub LoadDetails(ByVal order As Order)
        ' Define the delegate to callback into the process
        Dim callback As AsyncCallback = AddressOf OnOrderDetailsLoaded
    
        ' Reset the order binding collection.
        detailsBindingCollection.Clear()
    
        If order IsNot Nothing Then
            Try
                ' Begin the load related items.
                svcContext.BeginLoadProperty(order, "Order_Details", _
                    callback, svcContext)
            Catch ex As Exception
                messageTextBlock.Text = ex.Message
            End Try
        End If
    End Sub
    Private Sub OnOrderDetailsLoaded(ByVal result As IAsyncResult)
        ' Cache the result for the delegate.
        currentResult = result
    
        ' Use the Dispatcher to ensure that the 
        ' asynchronous call returns in the correct thread.
        Dispatcher.BeginInvoke(AddressOf OrderDetailsLoadedByDispatcher)
    
    End Sub
    Private Sub OrderDetailsLoadedByDispatcher()
        Dim response As QueryOperationResponse = Nothing
    
        ' Define the delegate to callback into the process
        Dim callback As AsyncCallback = AddressOf OnOrderDetailsLoaded
    
        Try
            ' Get the context from the result.
            svcContext = CType(currentResult.AsyncState, NorthwindEntities)
    
            ' Get the end result of the load operation.
            response = svcContext.EndLoadProperty(currentResult)
    
            ' Enumeration executes the query.
            For Each item As Order_Detail In response
                ' Load the item into the binding collection.
                detailsBindingCollection.Add(item)
            Next
    
            ' Get the continuation token from the response.
            itemToken = response.GetContinuation(Of Order_Detail)(Nothing)
    
            If Not itemToken Is Nothing Then
                ' Get the next page if a continuation token was returned.
                svcContext.BeginLoadProperty(currentOrder, "Order_Details", itemToken, _
                    callback, svcContext)
            Else
                ' Reset and rebind the grid to the items binding collection 
                ' and update the layout.
                Me.detailsGrid.DataContext = detailsBindingCollection
                Me.detailsGrid.UpdateLayout()
                Me.detailsGrid.Columns(0).Visibility = Visibility.Collapsed
                Me.detailsGrid.Columns(5).Visibility = Visibility.Collapsed
                Me.detailsGrid.Columns(6).Visibility = Visibility.Collapsed
            End If
        Catch ex As DataServiceQueryException
            messageTextBlock.Text = String.Format("Error: {0} - {1}", _
                ex.Response.StatusCode.ToString(), ex.Response.Error.Message)   
        End Try
    End Sub
    
            private void ordersGrid_SelectionChanged(object sender,
                SelectionChangedEventArgs e)
            {
                // Set the current order.
                currentOrder = (Order)ordersGrid.SelectedItem;
    
                // Clear the message text.
                messageTextBlock.Text = string.Empty;
    
                // Load details for the selected order.
                LoadDetails(currentOrder);
            }
    
            private void LoadDetails(Order order)
            {
                // Reset the order binding collection.
                detailsBindingCollection.Clear();
    
                if (order != null)
                {
                    try
                    {
                        // Begin the load related items.
                        svcContext.BeginLoadProperty(order, "Order_Details",
                            OnOrderDetailsLoaded, svcContext);
                    }
                    catch (Exception ex)
                    {
                        messageTextBlock.Text = ex.Message;
                    }
                }
            }
    
            private void OnOrderDetailsLoaded(IAsyncResult result)
            {
                // Use the Dispatcher to ensure that the 
                // asynchronous call returns in the correct thread.
                Dispatcher.BeginInvoke(() => 
                    {
                        QueryOperationResponse response = null;
    
                        try
                        {
                            // Get the context from the result.
                            svcContext = result.AsyncState as NorthwindEntities;
    
                            // Get the end result of the load operation.
                            response = svcContext.EndLoadProperty(result);
    
                            // Enumeration executes the query.
                            foreach (Order_Detail item in response)
                            {
                                // Load the item into the binding collection.
                                detailsBindingCollection.Add(item);
                            }
    
                            // Get the continuation token from the response.
                            itemToken = response.GetContinuation<Order_Detail>(null);
    
                            if (itemToken != null)
                            {
                                // Get the next page if a continuation token was returned.
                                svcContext.BeginLoadProperty(currentOrder, "Order_Details", itemToken,
                                    OnOrderDetailsLoaded, svcContext);
                            }
                            else
                            {
                                // Reset and rebind the grid to the items binding collection 
                                // and update the layout.
                                this.detailsGrid.DataContext = detailsBindingCollection;
                                this.detailsGrid.UpdateLayout();
                                this.detailsGrid.Columns[0].Visibility = Visibility.Collapsed;
                                this.detailsGrid.Columns[5].Visibility = Visibility.Collapsed;
                                this.detailsGrid.Columns[6].Visibility = Visibility.Collapsed;
                            }
                        }
                        catch (DataServiceQueryException ex)
                        {
                            messageTextBlock.Text = string.Format("Error: {0} - {1}",
                                ex.Response.StatusCode.ToString(), ex.Response.Error.Message);
                        }
                    }
                );
            }
    
    

To build and run the application

  1. From the Debug menu, select Start Debugging or Start Without Debugging.

    This builds and starts the application.

  2. When the page loads, enter a value in the Customer ID text box (a valid value of ALFKI is provided), and then click Get Orders.

    This displays the orders that belong to that customer.

  3. Click on a different order in the Orders grid.

    This displays the items for the selected order.

Next Steps

You have successfully enhanced the client application for Silverlight by adding the ability to load Order_Details objects that are related to a selected Order object. Next, you will update and delete existing Order_Details objects and save these changes to the data service:

Modifying and Deleting Entity Data

See Also

Other Resources