1. Problem
You need to implement CRUD operations on LOB data that includes complicated business logic.
2. Solution
Take advantage of WCF RIA Services features to support CRUD operations in a customizable way.
3. How It Works
You build on Recipe 7's code, updating the layout a bit, adding a button, and adding the star of the recipe: the DataForm
control. This is a very powerful record details editing control that
enables all CRUD operations directly. It can be templated and customized
from a UI perspective as well. For this recipe, you introduce the
control and focus on how to allow edits to happen on the client but
control when edits are sent to the server.
4. The Code
You start this recipe by opening the Recipe 8
properties dialog, enabling the WCF RIA Services link for the TestWeb
project, saving the project settings, and then recompiling. Then copy
the code from Recipe 7 where you databind via XAML and add sorting and paging as your starting point for this recipe.
Adjust the root Layout Grid and position on the filtering TextBox for space to add a Button that commits any edits to the server via WCF RIA Services. Next, add a DataForm control. The DataForm control can bind to either a collection of records or a single record. In this example, you want the DataForm to provide a details view of the selected record in the DataGrid.
To enable this, databind the DataForm.CurrentItem property to the DataGrid's SelectedItem property via Element databinding. Listing 1 has the XAML file code listing.
Listing 1. The Recipe 8 MainPage.Xaml File
<UserControl x:Class="Ch09_LOBApplications.Recipe9_8.MainPage" xmlns:dataControls= "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns:riaControls= "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:NorthwindData="clr-namespace:TestWeb.DomainService" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="600" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:dataFormToolkit= "clr- namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"> <UserControl.Resources> <NorthwindData:NorthwindDomainContext x:Key="NorthwindDomainContext" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="False"> <Grid.RowDefinitions> <RowDefinition Height="34" /> <RowDefinition Height="36" /> <RowDefinition Height="160" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> <riaControls:DomainDataSource x:Name="CustomersDomainDataSource" DomainContext="{StaticResource NorthwindDomainContext}" AutoLoad="True" QueryName="GetCustomersQuery" Grid.RowSpan="4"> <riaControls:DomainDataSource.SortDescriptors > <riaControls:SortDescriptor PropertyPath="CompanyName" Direction="Ascending"/> </riaControls:DomainDataSource.SortDescriptors> <riaControls:DomainDataSource.FilterDescriptors> <riaControls:FilterDescriptor PropertyPath="CompanyName" Operator="StartsWith" Value="{Binding Text, ElementName=FilterTextBox}" /> </riaControls:DomainDataSource.FilterDescriptors> </riaControls:DomainDataSource> <sdk:DataPager PageSize="5" Height="28" VerticalAlignment="Top" Grid.Row="1" Margin="0,3,0,0" Source="{Binding Data, ElementName=CustomersDomainDataSource, Mode=TwoWay}" /> <sdk:DataGrid x:Name="CustomersDataGrid" Grid.Row="2" Margin="2" Height="160" VerticalAlignment="Top" CanUserSortColumns="True" CanUserReorderColumns="True" CanUserResizeColumns="True" ItemsSource="{Binding Data, ElementName=CustomersDomainDataSource, Mode=TwoWay}" /> <StackPanel Margin="0,4,7,0" Orientation="Horizontal" d:LayoutOverrides="Width"> <TextBlock Height="29" x:Name="textBlock1" VerticalAlignment="Top" LineHeight="13.333" FontSize="13.333" HorizontalAlignment="Left" Width="355" Text="Enter The First Few Letters of the Company Name:" TextAlignment="Center" /> <TextBox x:Name="FilterTextBox" TextWrapping="Wrap" Width="73" Margin="0,2,0,4"/> <Button Content="Save To Server" Height="28" HorizontalAlignment="Left" Margin="30,0,0,0" x:Name="ButtonCommitToServer" VerticalAlignment="Top" Width="118" IsEnabled="True" Click="ButtonCommitToServer_Click" /> </StackPanel> <toolkit:DataForm Margin="2" Grid.Row="3" x:Name="CustomerDataForm" CurrentItem="{Binding SelectedItem, ElementName=CustomersDataGrid, Mode=TwoWay}" AutoCommit="False" AutoEdit="False" Header="Customer Details" /> </Grid> </UserControl>
|
Initially, when you drop the DataForm control onto the Grid and databind it to the DataGrid, AutoEdit defaults to True as does the AutoCommit property. Configure both AutoEdit and AutoCommit to false to gain more control over how edits are processed. This also enables the additional button editing UI on the DataForm control as shown in Figure 1.
Clicking the Edit
button (the pencil) on the Customer Details DataForm control allows the
user to perform CRUD operations. You configure the control explicitly to
display all of the buttons in the constructor for MainPage
after Initialization. The only other item to cover is the Save to
Server button. When you perform edits using the DataForm, they exist on
the client in the form of changes to the object representing each
database record. Because you disabled AutoCommit, you need to manually send any pending changes, as shown in Listing 2.
Listing 2. Recipe 8 MainPage.Xaml.cs File
using System.Windows; using System.Windows.Controls;
namespace Ch09_LOBApplications.Recipe9_8 { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); CustomerDataForm.CommandButtonsVisibility = DataFormCommandButtonsVisibility.All; }
private void ButtonCommitToServer_Click(object sender, RoutedEventArgs e) { if (CustomersDomainDataSource.HasChanges && !CustomersDomainDataSource.IsBusy) CustomersDomainDataSource.SubmitChanges(); } } }
|