How to: Using DomainDataSource
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
WCF RIA Services provides the DomainDataSource control to simplify the interaction between the user interface and the data from a domain context. With the DomainDataSource, you can retrieve, shape, and edit data using only declarative syntax. You specify the domain context to use the DomainDataSource, and then call the operations that are available through that domain context.
This topic is based on the WCF RIA Services example solution from the Walkthrough: Creating a RIA Services Solution.
In this topic:
- Configuring the Silverlight application for DomainDataSource
- Retrieving and displaying data
- Adding parameters to the query
- Sorting
- Grouping
- Filtering
- Editing
- Paging
Configuring the Silverlight Application for DomainDataSource
In order to use the DomainDataSource control, you must add a reference in the Silverlight project to the System.Windows.Controls.DomainServices assembly. This reference is automatically added when you drag the DomainDataSource from the Toolbox. Optionally, to use the DataGrid with DomainDataSource, you must also add a reference to System.Windows.Controls.Data. This reference is also automatically added when you drag the DataGrid control from the Toolbox.
The host control, for example the UserControl, must contain the following namespace reference:
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
Optionally, to use the DataGrid control with DomainDataSource, you must also add the following namespace:
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
In order to define the domain context in a declarative manner, you must include the namespace of the server project. In the following example, OA.SL.RIA.Demo.Web is the name of the server project. You will use the name of your project.
xmlns:domain="clr-namespace:OA.SL.RIA.Demo.Web"
Retrieving and Displaying Data
You specify a domain context for the DomainDataSource and provide the name of the method to use for loading data. Then you bind presentation controls such as the DataGrid to the DomainDataSource. A query method called GetCustomers() must exist on the domain service for the example to work.
[EnableClientAccess()]
public class SofiaCarRentalDomainService : OpenAccessDomainService<NorthwindDbContext>
{
public IQueryable<Customer> GetCustomers()
{
return this.DataContext.Customers;
}
}
<EnableClientAccess()>
Public Class SofiaCarRentalDomainService
Inherits OpenAccessDomainService(Of NorthwindDbContext)
Public Function GetCustomers() As IQueryable(Of Customer)
Return Me.DataContext.Customers
End Function
End Class
<UserControl x:Class="OA.SL.RIA.Demo.MainPage"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns:domain="clr-namespace:OA.SL.RIA.Demo.Web"
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices">
<Grid x:Name="LayoutRoot"
Background="White">
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomers"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}" />
</Grid>
</UserControl>
Adding Parameters to the Query
In some cases a query method requires parameter values. Typically, a query method requires a parameter value to filter the data that is returned. The DomainDataSource class provides the QueryParameters collection to facilitate adding parameters. The following example shows how to add a parameter value with a value that is specified in XAML.
A query method called GetCustomeById(), which accepts one parameter, must exist on the domain service for the example to work.
[EnableClientAccess()]
public class SofiaCarRentalDomainService : OpenAccessDomainService<SofiaCarRentalDbContext>
{
[Query( IsComposable = false )]
public Customer GetCustomerById( int customerId )
{
return this.DataContext.Customers.SingleOrDefault<Customer>( c => c.CustomerID == customerId );
}
}
<EnableClientAccess()>
Public Class SofiaCarRentalDomainService
Inherits OpenAccessDomainService(Of SofiaCarRentalDbContext)
<Query(IsComposable := False)>
Public Function GetCustomerById(ByVal customerId As Integer) As Customer
Return Me.DataContext.Customers.SingleOrDefault(Of Customer)(Function(c) c.CustomerID = customerId)
End Function
End Class
<Grid x:Name="LayoutRoot"
Background="White">
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomerById"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.QueryParameters>
<riaControls:Parameter ParameterName="customerId"
Value="1" />
</riaControls:DomainDataSource.QueryParameters>
</riaControls:DomainDataSource>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}" />
</Grid>
You can also add a parameter that uses a value from the user for the query. You bind a Parameter object to the user-input that contains the value that will be used in the query. The following example shows how to specify a value from a ComboBox, used as the parameter value.
<Grid x:Name="LayoutRoot"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomerById"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.QueryParameters>
<riaControls:Parameter ParameterName="customerId"
Value="{Binding ElementName=idsCombo, Path=SelectedItem.Content}" />
</riaControls:DomainDataSource.QueryParameters>
</riaControls:DomainDataSource>
<ComboBox Width="80"
x:Name="idsCombo">
<ComboBoxItem Content="1" />
<ComboBoxItem Content="2" />
</ComboBox>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}" Grid.Row="1" />
</Grid>
Sorting
The DomainDataSource provides the SortDescriptors collection to facilitate sorting of the data. In the SortDescriptors collection, you add SortDescriptor instances that describe the values to be used for sorting the collection. You can add as many SortDescriptor instances as you want to provide layers of sorting. You can specify whether the data is sorted in ascending or descending order. The following example shows how to use a sort descriptor to the DomainDataSource. The data retrieved from the query is sorted by the FullName property in descending order.
<Grid x:Name="LayoutRoot"
Background="White">
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomers"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.SortDescriptors>
<riaControls:SortDescriptor Direction="Descending"
PropertyPath="FullName" />
</riaControls:DomainDataSource.SortDescriptors>
</riaControls:DomainDataSource>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}"/>
</Grid>
Grouping
The DomainDataSource provides the GroupDescriptors collectionto to facilitate grouping the data by property values. In the GroupDescriptors collection, you add GroupDescriptor instances that define the value to be used for grouping. You can add as many GroupDescriptor instances as needed.
<Grid x:Name="LayoutRoot"
Background="White">
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomers"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.GroupDescriptors>
<riaControls:GroupDescriptor PropertyPath="City" />
</riaControls:DomainDataSource.GroupDescriptors>
</riaControls:DomainDataSource>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}"/>
</Grid>
Filtering
The DomainDataSource control provides the FilterDescriptor collection to enable you to filter the data that is returned by the query. By adding filters, you can specify that only entities which meet the condition in the filter are loaded from the domain context. The following example shows two filter descriptors that are connected by a logical AND statement. One filter depends on the user input and one filter is specified in the declarative syntax.
<Grid x:Name="LayoutRoot"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomers"
AutoLoad="True">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.FilterDescriptors>
<riaControls:FilterDescriptor PropertyPath="Country"
Operator="IsEqualTo"
Value="USA" />
<riaControls:FilterDescriptor PropertyPath="FullName"
Operator="StartsWith"
Value="{Binding ElementName=namesCombo, Path=SelectedItem.Content}" />
</riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>
<ComboBox x:Name="namesCombo"
Width="70"
SelectedIndex="0">
<ComboBoxItem Content="J" />
<ComboBoxItem Content="K" />
<ComboBoxItem Content="C" />
</ComboBox>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}"
Grid.Row="1" />
</Grid>
Editing
To persist data modifications, call the SubmitChanges method on the DomainDataSource object. To cancel changes, call the RejectChanges method.
Paging
When displaying a large number of entities, you may wish to provide paging in your user interface. The DomainDataSource control enables you to specify the number of entities to load and the number of entities to be displayed on a page.
If you use the DataPager in an application with a Telerik Data Access for data store you must order the data returned by your queries for the DataPager to work correctly. Telerik Data Access does not support paging of data without an OrderBy clause in the query method or sorting specified on the Silverlight client.
The following example shows paging with the DomainDataSource.
<Grid x:Name="LayoutRoot"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<riaControls:DomainDataSource x:Name="DataSource"
QueryName="GetCustomers"
AutoLoad="True"
LoadSize="3"
PageSize="3">
<riaControls:DomainDataSource.DomainContext>
<domain:SofiaCarRentalDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.SortDescriptors>
<riaControls:SortDescriptor PropertyPath="FullName" />
</riaControls:DomainDataSource.SortDescriptors>
</riaControls:DomainDataSource>
<data:DataGrid ItemsSource="{Binding ElementName=DataSource, Path=Data}"
Grid.Row="0" />
<data:DataPager Grid.Row="1"
Source="{Binding ElementName=DataSource, Path=Data}" />
</Grid>