Over the weekend, I saw a question on StackOverflow about combining .NET RIA Services and the ViewModel pattern and answered briefly there, but the topic is worthy of a blog post.
At a high level, .NET RIA Services generates a data model for use in the client presentation tier based on the application logic you author for the server portion of your application. The question is how could/should this data model fit into a view model. I blogged about the ViewModel pattern a long while back in the context of mySilverlight.FX work. This post will take care of a few things at the same time: (a) show how the two work together, and (b) show how the work in Silverlight.FX itself has evolved over time.
For most of the post, I’ll walk you through a basic .NET RIA Services application. I’ll of course use my favorite scenario, a Product catalog.
Data Model on Server
For my server end of things, I’ll define my data model under a DataModel folder/namespace. For this app, I’ll have a Product class as my entity type and a ProductRepository class that contains a static list of products (for simplicity) to serve as my data access layer.

Domain Logic on Server
The first step is to define the set of operations on the middle tier. This is where I’ll use .NET RIA Services to package up that application logic in the form of a DomainService. The point of the “DomainService” name is that it is the stateless object that represents a specific domain that is characteristic of my application. My application is a simple product catalog, and correspondingly I’m going to name my class Catalog. Its going to have a simple method for searching the products in the catalog.
namespace MyApp.DomainLogic { [EnableClientAccess] public class Catalog : DomainService { public IQueryable<Product> GetProducts(string keyword) { if (String.IsNullOrEmpty(keyword)) { return null; } keyword = keyword.ToLower(); ProductRepository repository = new ProductRepository(); return from p in repository.FindAllProducts() where (p.Name.ToLower().IndexOf(keyword) >= 0) || (p.Description.ToLower().IndexOf(keyword) >= 0) select p; } } }
Generated Data Model on Client
Since I marked this class with [EnableClientAccess], the .NET RIA Services tooling generates a corresponding Catalog DomainContext representing the client-side data model with the following significant members: a list of products, and a method to load that list of products. Behind the scenes, the method consumes the query method I defined on the server to fetch the matching list of products.
namespace MyApp.DomainLogic { public partial class Catalog : DomainContext { public EntityList<Product> Products { get { ... } } public void LoadProducts(string keyword); } }
XAML View
The next step I am going to take up is defining the view itself. I am going to use a DataGrid control for display a list of search results, and a DataForm control for displaying details of the selected product. Here are the significant pieces of the overall XAML markup:
<UserControl> <TextBox x:Name="searchTextBox" VerticalAlignment="Center" /> <Button x:Name="searchButton" Content="Search" /> <ProgressBar x:Name="searchProgressBar" Opacity="0" IsIndeterminate="True" /> <dg:DataGrid x:Name="productsGrid" SelectionMode="Single"> <dg:DataGrid.Columns> ... </dg:DataGrid.Columns> </dg:DataGrid> <df:DataForm x:Name="productForm" Header="Product"> <df:DataForm.DisplayTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Name}" FontWeight="Bold" /> ... </StackPanel> </DataTemplate> </df:DataForm.DisplayTemplate> </df:DataForm> </UserControl>
The Associated View Model
This XAML doesn’t have any functionality yet. For that I am going to implement my view model class, and then hook the two up together. My view model is going to allow searching for products, and supplying the list of resulting products. It is also going to track the selected product as the user changes the selection. Here is the code:

public class SearchViewModel : Model { private Catalog _catalog; private Product _selectedProduct; public SearchViewModel() { _catalog = new Catalog(); _catalog.Loaded += OnCatalogLoaded; } public IEnumerable<Product> Products { get { return _catalog.Products; } } public Product SelectedProduct { get { return _selectedProduct; } set { if (_selectedProduct != value) { _selectedProduct = value; RaisePropertyChanged("SelectedProduct"); } } } public event EventHandler SearchCompleted; public event EventHandler SearchStarting; private void OnCatalogLoaded(object sender, LoadedDataEventArgs e) { SelectedProduct = _catalog.Products.FirstOrDefault(); RaisePropertyChanged("Products"); if (SearchCompleted != null) { SearchCompleted(this, EventArgs.Empty); } } public void Search(string keyword) { keyword = keyword.Trim(); if (keyword.Length == 0) { return; } if (SearchStarting != null) { SearchStarting(this, EventArgs.Empty); } _catalog.Products.Clear(); _catalog.LoadProducts(keyword); } }
The first thing to notice is the use of the Model base class, which is a utility class offered by Silverlight.FX that takes care of implementing INotifyPropertyChange, as well as caching and batching property change events.
The view model encapsulates the underlying data model that was generated in the form of a Catalog class and its Products entity list. In turn the view model exposes a Search operation (which takes in a keyword), and the list of resulting products. It also supports tracking selection via a SelectedProduct property.
Associating the View and its ViewModel
Now that we have both our view and view model, it is time to hook the two up together.
Instead of using UserControl has my root element, I am going to use Window, a derived UserControl from Silverlight.FX, as it has functionality to associate a ViewModel instance. Specifically it instantiates the view model, sets it as the DataContext, and also associates it as the model for the all elements contained within its scope. We’ll see that used in a moment.
<fxui:Window xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX" ModelType="SearchViewModel"> ... </fxui:Window>
Next I’ll use standard data-binding to bind properties in the view to properties on the view model.
<dg:DataGrid x:Name="productsGrid" ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct, Mode=TwoWay}"> ... </dg:DataGrid> <df:DataForm x:Name="productForm" CurrentItem="{Binding SelectedProduct}"> ... </df:DataForm>
Next I want to hook up the Search button to the Search method on the view model to trigger the loading of the matching products. The Search operation is essentially a command, and while a command binding could be used (also supported in Silverlight.FX), instead I am going to use a much simpler concept as introduced in Silverlight.FX – an invoke script action that is equivalent to binding events to methods.
<Button x:Name="searchButton" Content="Search" fxui:Interaction.Action="$model.Search(searchTextBox.Text)"/>
Interaction.Action is a shortcut for associating an InvokeScriptAction on Click trigger associated with a Button. Here I am referring to the associated model, using $model, and then invoking the Search method on it. As the search method takes in a string parameter, I am passing in the Text property of the searchTextBox in. The action takes care of finding the textbox control, and retrieving its text.
Finally my SearchViewModel class exposes a couple of events. I’d like to handle those events in the view, and respond accordingly. Specifically, I want to hide/show the progress bar in response to the SearchCompleted and SearchStarting events. To do that I am going to define two visual states for my view.
<vsm:VisualStateManager.VisualStateGroups> <vsm:VisualStateGroup x:Name="SearchStates"> <vsm:VisualState x:Name="Searching"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="searchProgressBar" Storyboard.TargetProperty="Opacity"> <EasingDoubleKeyFrame KeyTime="00:00:0.25" Value="1"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </vsm:VisualState> <vsm:VisualState x:Name="Searched"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="searchProgressBar" Storyboard.TargetProperty="Opacity"> <EasingDoubleKeyFrame KeyTime="00:00:0.25" Value="0"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </vsm:VisualState> </vsm:VisualStateGroup> </vsm:VisualStateManager.VisualStateGroups>
And I’ll use event triggers provided by Silverlight.FX to respond to those events, and declaratively perform visual state transitions.
<fxui:Window xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX" ModelType="SearchViewModel"> <fxui:Interaction.Triggers> <fxui:EventTrigger SourceName="$model" EventName="SearchStarting"> <fxaction:GoToState StateName="Searching" /> </fxui:EventTrigger> <fxui:EventTrigger SourceName="$model" EventName="SearchCompleted"> <fxaction:GoToState StateName="Searched" /> </fxui:EventTrigger> </fxui:Interaction.Triggers> </fxui:Window>
Here again you’ll see the use of $model. By default EventTrigger listens to events on the associated view element (i.e. fxui:Window in this case), but specifying sourceName to be $model tells the event triggers to listen to events on the associated model. The actions, fxaction:GoToState declaratively transitions visual states.
There you have it. The view is now hooked up to the properties, methods and events on the view model, and our application works end-to-end, for this simple search scenario.
Designer/Developer Workflow and Going Further
The view model is completely decoupled from the view. The developer can focus on the data model, domain logic and view models in the application, while the designer can focus on creating the best user experience in the view. Bringing these two worlds together involves binding and hooking the view to its associated view model using various declarative constructs – such as data-binding, actions, triggers and commands.
Of course the designer can add other interactivity to the view as well… without necessarily writing lots or on many occasions, any code. Since this is a search form, I’d like to have the enter key press within the textbox to automatically trigger the Click event of the search button. That can be simply done by attaching the AutoCommit behavior to the TextBox:
<TextBox x:Name="searchTextBox"> <fxui:Interaction.Behaviors> <fxui:AutoCommit ButtonName="searchButton" /> </fxui:Interaction.Behaviors> </TextBox>
Similarly, I could also add an AutoComplete behavior from Silverlight.FX to the same textbox to add in some functionality to remember the last few searches, a Watermark behavior to include an inline prompt, and so on.
The ViewModel Pattern At Play
I’ve got a slightly revised diagram from when I initially posted a while back.

The key points here are:
- The generated Entity types and DomainContext from .NET RIA Services form the data model. They are designed to be bindable. They support change notifications, expose operations etc. So while they can be used as a view model directly, often times you will in fact have client-side application logic, and will expose bits of your data model through a separate view model type you author.
- I personally like to think of a view model type as any vanilla class in terms of its structure: properties, methods and events at the very least, and optionally, but almost always, change notifications as a special type of event. The view model is decoupled from the view. The consumer might be a view, and it might also be unit test.
- The view is mostly XAML, and while it might contain minimal code-behind, declarative building blocks like behaviors, actions, and triggers go a long way in helping express interactivity through XAML. The view binds to its associated view model to get/set properties, invoke methods, and listen to events.
You can download the entire project along with all the source code. You’ll need to install the Silverlight 3 developer runtime and tooling along with the .NET RIA Services CTP to compile and run the app. Note that the Silverlight.FX functionality itself works in Silverlight 2 as well.
Enjoy!
No tags
