(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern

(19 votes)
Brian Noyes
>
Brian Noyes
Joined Jun 10, 2010
Articles:   19
Comments:   116
More Articles
34 comments   /   posted on Aug 03, 2010

This article is Part 4 of the series WCF RIA Services.

Introduction

The Model-View-ViewModel pattern (MVVM) is a very popular approach for building more loosely coupled Silverlight and WPF applications. I won’t attempt to full define and explain the pattern here, but will give a quick explanation of what it is about and why you would want to use it. At a high level, MVVM is an alternative or evolution of MVC and MVP patterns, but taking full advantage of the rich data binding, commands, and behaviors that we have available to us in Silverlight and WPF. The view model’s primary responsibility is to offer up state to the view in the way the view wants to see it. It exposes properties that the view can easily bind to that let the view display the data it needs and to also hook up commands and behaviors that point back to the view model to invoke interaction logic that the view model encapsulates. The view model is all about containing and manipulating the data that the view needs and providing the interaction logic to support the view. The view model acts as a translator from the complex world of the overall application model to the specific set of data that a single view needs, structured in the way the view needs to display it. Structurally, you typically set the view’s DataContext equal to an instance of the view model so that the view can easily bind to the exposed properties of the view model. There are many ways to get this hook up done.

The motivations for using it include the fact that it allows you to work on the view and the view model mostly in isolation, facilitating developer/designer workflow. Additionally, by separating your interaction logic into the view model, you can more easily unit test that logic because it is not tightly woven with the UI itself. And finally, the pattern just provides a clean separation of responsibility so the view can just be about the structure and visual behavior of what you see on the screen, and the view model can just be about the data and logic surrounding the data that the view needs to support it. For more in depth coverage, I recommend you read Josh Smith’s excellent article on MVVM, as well as the guidance being developed by the Microsoft patterns & practices Prism team in Prism 4 at http://prism.codeplex.com/. Prism 4 is due out in the September/October timeframe but there are already public drops in the downloads section on CodePlex.

So now let’s see how MVVM fits with WCF RIA Services. The starting point code for this article will be the sample code from Part 3 of the series, which you can download here. You can download the finished code for this article here.

Step 1: Factor out a view model

In the last article’s version of the TaskManager application, I was already starting to have a fair amount of code building up in the code behind of the view (the MainPage user control), even with such a simple application. The first step is to factor that code out into a view model. Create a new class named TasksViewModel in the project. Often a good way to get started defining your view model is to analyze the view and determine what properties would be needed to support it. The image below shows the form as it is currently defined. To clean things up a bit, I’ve replaced the two TextBoxes for date input at the top with DatePickers, removed the unused properties on the Task from the DataGrid, and reordered the columns to look a little better.

figure1

By looking at the UI design, you can identify 6 properties the view model should expose to support this view: two DateTime properties for lower and upper dates for a search; three commands to support searching by date, adding a task, and saving changes; and one Tasks collection. In its simplest form, that would look like this:

 public class TasksViewModel
 {
     public DateTime LowerSearchDate { get; set; }
     public DateTime UpperSearchDate { get; set; }
     public ICommand SearchByDateCommand { get; set; }
     public ICommand AddTaskCommand { get; set; }
     public ICommand SaveChangesCommand { get; set; }
     public IEnumerable<Task> Tasks { get; set; }
 }

However, you generally need to implement INotifyPropertyChanged on your view model which requires the expanded syntax for each property so that the UI can stay fresh through its data bindings if the bound property on the view model changes, so each property definition should look more like this in its full form, except possibly the private set properties that the view model sets once and does not change.

 public class TasksViewModel : INotifyPropertyChanged
 {
     public event PropertyChangedEventHandler PropertyChanged = delegate { };
     DateTime _LowerSearchDate;
     public DateTime LowerSearchDate
     {
         get
         {
             return _LowerSearchDate;
         }
         set
         {
             if (value != _LowerSearchDate)
             {
                 _LowerSearchDate = value;
                 PropertyChanged(this, new PropertyChangedEventArgs("LowerSearchDate"));
             }
         }
     }

To support the ICommand properties, you will need a decent command implementation. I’ve included a simple RelayCommand implementation, but normally in real projects I use the DelegateCommand from Prism.

A view model is all about managing the data needed by a view, and a DomainContext in RIA Services is all about providing and tracking changes to the data, so a simple approach to using RIA Services with MVVM is to simply use a DomainContext within your view model.

 TasksDomainContext _Context = new TasksDomainContext();
  
 public TasksViewModel()
 {
     SearchByDateCommand = new RelayCommand<object>(OnSearchByDate);
     AddTaskCommand = new RelayCommand<object>(OnAddTask);
     SaveChangesCommand = new RelayCommand<object>(OnSaveChanges);
     Tasks = _Context.Tasks;
     if (!DesignerProperties.IsInDesignTool)
     {
         _Context.Load(_Context.GetTasksQuery());
     }
 }

Here I have made the TasksDomainContext a member of the view model, and initialized the commands in the constructor to point to methods within the view model. The Tasks property exposed by the view model just holds a reference to the Tasks entity collection exposed by the domain context, which will raise INotifyCollectionChanged events to keep the view fresh when the collection changes, which will happen on the initial load, when you add Tasks, and when SubmitChanges completes and has updated entities from the back end. Notice the use of the DesignerProperties.IsInDesignTool property to prevent calling Load in the designer, which would break it.

Next is to move the methods that were in the code behind of MainPage into the view model. I’ve cleaned them up a bit in the process too. Note that the search method now leverages the deferred execution I talked about in Part 3, making the GetTasksByStartDate domain service method unnecessary since the client can specify that search expression itself. I’ve also moved the creation of a new Task into a simple popup ChildWindow so you can actually edit the values. Note the commend in the code below – showing a dialog from a view model is really a no-no, just doing it here because the focus is on RIA Services, not on full MVVM patterns. 

 private void OnSearchByDate(object param)
 {
     _Context.Tasks.Clear();
     EntityQuery<Task> query = _Context.GetTasksQuery();
     LoadOperation<Task> loadOp = _Context.Load(query.Where(t => t.StartDate >= LowerSearchDate && t.StartDate <= UpperSearchDate));
 }
  
 private void OnAddTask(object param)
 {
     // Generally don't want to do this for testability reasons
     // Simplification because MVVM structuring is not the focus here
     // See Prism 4 MVVM RI for a cleaner way to do this
     AddTaskView popup = new AddTaskView();
     popup.DataContext = new Task();
     popup.Closed += delegate
     {
         if (popup.DialogResult == true)
         {
             Task newTask = popup.DataContext as Task;
             if (newTask != null) _Context.Tasks.Add(newTask);
         }
     };
     popup.Show();
 }
  
 private void OnSaveChanges(object param)
 {
     _Context.SubmitChanges();
 }

At this point you have you have a functioning view model, now I’ll clean up the view to work with the view model.

Step 2: Hook up the view to the view model

From Part 1, the view was using the DomainDataSource that was generated from the drag and drop. If you want a clean MVVM design, you will unfortunately have to pass on using DomainDataSource. That object is effectively putting state management and query logic into the XAML itself, which violates the clean separation of responsibilities followed in MVVM.

So basically I took the existing view, deleted out the DomainDataSource, and added appropriate bindings to each of the controls to bind to the exposed view model properties as shown below. For a top level view like this, constructing the view model in the XAML to set it as the data context is a simple way to get the view’s data context set to an instance of the view.

 <UserControl x:Class="TaskManager.MainPage" ...>
     <UserControl.DataContext>
         <local:TasksViewModel/>
     </UserControl.DataContext>
         <Grid x:Name="LayoutRoot" Background="White">
         <sdk:DataGrid ItemsSource="{Binding Tasks}" .../>
         <Button Command="{Binding SearchByDateCommand}" .../>
         <Button Command="{Binding AddTaskCommand}" ... />
         <Button Command="{Binding SaveChangesCommand}" ... />
         <sdk:DatePicker SelectedDate="{Binding LowerSearchDate}" ... />
         <sdk:DatePicker SelectedDate="{Binding UpperSearchDate}" ... />
     </Grid>
 </UserControl>

Lastly, remove all the code from the code behind of the view, since it is no longer being used (all the button click handlers were removed in the process of hooking of the commands with bindings to the view model properties).

 public partial class MainPage : UserControl
 {
     public MainPage()
    {
         InitializeComponent();
     }
 }

Summary

The simplest way to use WCF RIA Services with the MVVM pattern is to stop using the DomainDataSource in your views and to use a domain context as the repository of data for your view models. You can still leverage the drag and drop Data Sources window features, you just have to do a little clean up to delete off the DomainDataSource after the drop and touch up the bindings a little.

There are two downsides to the approach as I have shown it here: testability and separation of concerns. One of the benefits of the MVVM pattern is supposed to be unit testability. But with a concrete type dependency on the domain context type in your view model, you are out of luck for mocking out that dependency. There are two approaches possible to address this:

  1. Use dependency injection to provide the domain context to the view model, and create a mock DomainClient and pass it to the DomainContext. This allows your view model to keep using the full functionality of the DomainContext, but you are able to mock out the calls to the service underneath the DomainContext. This approach is outlined in this post. I’ll be providing an example in Part 8 of this series, which is focused on testability.
  2. Factor out the DomainContext to a repository service that defines an interface similar to the DomainContext API and consume that from the view model. This would allow you to mock your repository service that contains the domain context. It would also address the separation of concerns problem, because then you would be separating the implementation choice of using RIA Services from the view model, which should really be separated. However, you would give up a lot of flexibility in the view model and it would not be an easy repository implementation.

Neither of these approaches is particularly easy. I’ll cover them in more detail later in part 8, and may blog some more on this topic as well. That’s all for now. You can download the finished code for this article here. See you next time.

About the Author

Brian Noyes is Chief Architect of IDesign, a Microsoft Regional Director, and Connected System MVP. He is a frequent top rated speaker at conferences worldwide including Microsoft TechEd, DevConnections, DevTeach, and others. He is the author of Developing Applications with Windows Workflow Foundation, Smart Client Deployment with ClickOnce, and Data Binding in Windows Forms 2.0. Brian got started programming as a hobby while flying F-14 Tomcats in the U.S. Navy, later turning his passion for code into his current career. You can contact Brian through his blog at http://briannoyes.net.


Subscribe

Comments

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Thomas H. Lanier on Aug 09, 2010 23:46

    The downloaded code for this article has a couple problems.

    In AddTaskView.xaml.cs the OkButton_Click should be named SaveButton_Click.

    In MainPage.xaml

    Add Mode=TwoWay to the bindings for the DatePickers:
    "{Binding LowerSearchDate, Mode=TwoWay}"
    "{Binding UpperSearchDate, Mode=TwoWay}"

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by VenkatRaman on Aug 11, 2010 13:55

    Please let us know how to edit records. For adding you will add something like  _Context.Tasks.Add(newTask);. 

    Thanks in advance

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Aug 11, 2010 14:57

    Hi Venkat, The sample already supports editing. You can edit the tasks in the grid and press the Save Changes button and the changes will be persisted to the back end. Basically the domain context tracks changes to the objects it has retrieved based on property changed events that they fire when you edit them. Then when you call SubmitChanges on the domain context, it sends all the changed entities back to your domain service so it can persist those changes.

    I'll also be showing adding and displaying child entities in the next article (Part 5), which should be out within a week.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by seonsoo on Aug 26, 2010 11:21

    nice article

    please keep them posting!

    especially looking forward to topics on structuring & architecting SL 4 Applications using RIA Services + MVVM that's blendable and testable.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Mohsen on Aug 28, 2010 13:51

    Hi, thank you for your brief and useful article. i have a question here..by removing DomainDataSource we actually lose some facilities alike paging... do you have any idea how can i add paging in this approach?


  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by seonsoo on Aug 31, 2010 03:52

    @Mohsen

    Check out PagedCollectionView class

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by PCDiver on Sep 03, 2010 14:34
    Why don't you make the domaindatasource part of the VM?  This way you keep the paging functionality without having to go the PagedCollectionView road.
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Sep 03, 2010 17:58

    PCDiver -

    A couple reasons for not putting the DomainDataSource in the VM...

    1) Its a control, and putting a control in a VM is just wrong :)

    2) As a control, it would have issues with manipulating it on a background thread, whereas you can work with the collections of the domain context in the background.

    3) Even though it does not do rendering itself, the fact that it is a control means it may not play well in a unit test environment, and testability is again one of the main motivators for doing MVVM

    4) It makes your VM even more coupled to the fact that you are using WCF RIA Services as a data retrieval and update mechanism, and ideally the VM should be decoupled from how it gets its data, it should just be about what it does with that data to support the view (note - putting the domain context into the VM suffers this same problem, just to a slightly lesser degree because it would be a little easier to wrap the domain context in a repository like interface to decoupled the VM than I think it would be to wrap the DomainDataSource.

    So while you could do it structurally, I think you are giving up too much by doing so.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by PCDiver on Sep 05, 2010 13:03

    Brian,

    Thanks for taking the time to answer my question.

    about 1.  If a control can be used without UI, why is it wrong to use it in a VM?

    about 2. The domain context can still be accessed via the DDS and so all the collections.  I'm not sure what you mean with the problems of accessing a control on a background thread.  Can this not be done? (limited experience here)

    about 3.  Can you give an example why a control would not work in a unit test?

    about 4. I don't see the difference between wrapping a domain context in a repository and doing so for a DDS.

    I expose my DDS via a property in my VM.  I bind directly to the VM not the DDS. If later on I decide to change my DDS to something else, like a paged collection, I just replace my DDS.  That means no changes to the view, only in the VM, and isn't that what MVVM is about?

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Anders Øyvind on Sep 10, 2010 17:15

    Hi.

    I just downloaded the project that one can start with on this part of the series, added a reference in web.config to an existing sql server 2005, and created the taskmanager database using the script given.

    Adding a new row and save the changes gave me an error, and checking the SubmitOperation I found that my dbms-version didn't support datetime2.

    So, yes, I did use sql server 2005, and switching to sql server 2008 express r2, it worked as it should. However, from what I see, the startdate is defined as a datetime data type in your entity model. Where is this defined? Can an attribute be set in the domain servrice metadata, that the field is a regular datetime?

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Sep 10, 2010 17:59
    Hi Anders, I've run into this in classes as well. Let me do a little research and get back to you. It is indeed tied to having created the solution on a SQL 2008 R2 database, but likewise I have had a hard time tracking down exactly where that dependency is defined and how to quickly change it. I'll post another comment once I've solved it.
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Sep 10, 2010 18:10

    PCDiver

    A general answer to your specific questions about why not to put controls in VMs is that in some cases it might work, but in others not so it is generally a bad practice. And by work, I am specifically referring to working in a unit test environment. It is also just a weakening of the clean separation of concerns. If you let that control in there, are you also going to start letting others? Where do you draw the line? The point is to keep it simple and make it so there are clean definitions of what goes where.

    An example of where it won't work well. The other day on the Prism team, we were writing some unit test for a behavior. In this specific case, the behavior is something that is intended to go in the view definition, so it is OK to reference controls in there. The specific behavior was to simulate the UpdateSourceTrigger.PropertyChanged option that a binding in WPF has but Silverlight does not. We were trying to write a unit test to verify that the behavior updates the bound property when the Text property changes. It wasn't working. So we tried to write an even simpler test. As far as the object model of the TextBox class is concerned, Text is just a .NET property and there is a corresponding TextChanged property that is supposed to fire when you set the Text. Based on that API, I should be able to write a test that sets the Text property and confirms that the TextChanged event fires. We did that. FAIL. Why? It turns out that in the implementation of the TextBox, which is a control, they don't fire that event unless the control has been RENDERED. It is a control, it assumes it is going to be used in a UI context, and it modifies its behavior based on that.

    That is why putting controls into a view model is a bad idea in general. Controls have a reasonable presumption that by design, they are for use in a rendered UI context. They may not behave the same if not in that UI context, and so won't unit test consistent with their design.

    Hope that helps clarify. Just cause it might work for DDS doesn't mean it is a good idea. And because DDS derives from Control, I am not willing to presume that it will work consistently for all of its behavior if it is not in a UI context.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Anders Øyvind on Sep 11, 2010 00:07

    Brian, thanks for looking into it. I decided to take a look myself, in hopes of getting an answer to it, I found that if I make a model of a table with a datetime2 data type, I'd get something like the following in my model.edmx-file:

    <EntityType Name="test">
    <Key>
    <PropertyRef Name="id" />
    </Key>
    <Property Name="id" Type="int" Nullable="false" />
    <Property Name="name" Type="nchar" MaxLength="10" />
    <Property Name="dato" Type="datetime" />
    <Property Name="dato2" Type="datetime2" />
    </EntityType>

    Pretty clear, and also visible through TestModel.Store -> TestDatabase -> Test table -> type property in the model browser. 

    In YOUR project, though, I couldn't find any trace of datetime2 in the model. Made me believe that the schema was interpreted differently by some version attribute or alike.

    ProviderManifestToken="2005" or "2008". Attribute of the "TaskManagerModel.Store" schema. A google search seemed to confirm it. Funny still, that a definition of datetime in the schema makes the framework pop up with an idea of datetime2.

    So. In order to have backward compatibility, I have two options: Stick with sql server 2005 or modify the edmx-xml manually after creation. Am I right? I guess an attribute to the properties sheet in VS shows up eventually.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by eric yan on Oct 06, 2010 16:53
    Hello, I have a question, when I want to delete a task, how can I know what item in the DataGrid hasing been selected? Let ViewModel to know the View or fire a event to the ViewModel from the View? thanks.
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Oct 06, 2010 16:56

    Hi Eric,

    Not really a RIA Services question, but in a ViewModel world I would typically bind the SelectedItem property of the DataGrid (or any Selector - i.e. ListBox, ComboBox, etc.) to a property exposed by the view model (i.e. CurrentTask) so that the ViewModel always knows what the selected item is and can act on it.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by eric yan on Oct 07, 2010 09:31
    Brian, thanks, Now it works, but I have another question, how can I capture the SelectionChanged event from the DataGrid? I try to define a  SelectionChangedEventHandler in the ViewModel file, but I can't bind it to  SelectionChanged property of the DataGrid, thank you.
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Oct 07, 2010 18:34

    Eric,

    To handle events from the view in the view model that do not have correponding events, you either need to bind a corresponding property on the control that changes when the event fires to a property in the view model (i.e. SelectedItem property instead of handling the SelectionChanged event) or you need to use behaviors such as Blend InvokeCommandAction or CallMethodAction behaviors to hook the event in the view and call functionality on the view model.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by eric yan on Oct 08, 2010 16:09
    very nice, that's works.but I think the TextChangedEvent is more difficult to deal with.is there a easy way...?
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Keith Safford on Oct 08, 2010 19:09

    Brian,

    First off, thanks for the tutorials.  I have been anxiously awaiting the MVVM one and went through the tutorial.  However, when I ran it, I received a VS Just-In-Time Debugger error.  Then, I ran the completed, downloaded code and received the same error.  The error is:
    An Unhandled Exception ('Unhandled Error in Silverlight Application Code: 4004
    Category: ManagedRuntimeError
    Message:
    System.ServiceModel.DomainServices.Client.DomainOperationException:

    but that was it.  I did a search and some on the web who received a 4004 error and more information after the Client.DomainOperationException.  But that was all I had.  Anyone have any ideas on what is going on?  I will do more searching on the web.

     

     

     

     

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Oct 08, 2010 19:32

    Eric,

    Take a look at the behavior in the code for Part 5 - I have a behavior in there that hooks the TextBox.TextChanged event to simulate the UpdateSourceTrigger.PropertyChanged option that WPF has. You could instead route the call to your view model through a command or method call.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Keith Safford on Oct 08, 2010 20:45

    Brian,

    First off, thanks for the tutorials.  I have been anxiously awaiting the MVVM one and went through the tutorial.  However, when I ran it, I received a VS Just-In-Time Debugger error.  Then, I ran the completed, downloaded code and received the same error.  The error is:
    An Unhandled Exception ('Unhandled Error in Silverlight Application Code: 4004
    Category: ManagedRuntimeError
    Message:
    System.ServiceModel.DomainServices.Client.DomainOperationException:

    but that was it.  I did a search and some on the web who received a 4004 error and more information after the Client.DomainOperationException.  But that was all I had.  Anyone have any ideas on what is going on?  I will do more searching on the web.

     

     

     

     

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Oct 08, 2010 22:19

    Keith,

    Take a look at the code for Part 7, which has a callback for the load calls on the service. Most likely you don't have the database set up or have a connection string problem. That will result in an exception being thrown to the client, and if unhandled in the client, RIA Services will raise it as an unhandled exception. You should be able to put a breakpoint in the unhandled exception handler in the App class to see the exception. In the later parts I added the callback handler, which is your opportunity to see that there is an error,  do something about it, and then mark it as handled so that it doesn't blow up the app. I'll be talking more about that pattern in Part 8, which I am a bit behind on getting out.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Keith Safford on Oct 11, 2010 16:31

    Brian,

    Ok, I figured out what it was.  I was using SQL Server 2005 (hopefully we are going to move to 2008 soon) and the ProviderManifestToken was set to 2008 and when I changed it to 2005 all worked.  Gotta love this stuff, never a dull moment!

    Keith

     

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Olusola Adio on Oct 13, 2010 13:03

    Brian,

    Thanks for this MVVM-RIA article. This is very concise and well understandable.  Please keep up the good work.

    Olusola Adio

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Olusola Adio on Oct 13, 2010 16:43

    Brian,

    This series is so nice. Have you thought of making the parts of this series into chapters of a book/mini-book on WCF/RIA. Maybe an additional chapter on RIA deployment. You can exploit these digital publishing facilities like Amazon Kindle if you don't have the time to do business with paperback publishers. I'll be your first buyer. There are other WCF/RIA materials but this series is brief and straight to the point.

    Regards, Olusola

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Oct 13, 2010 21:04

    Hi Olusola,

    I have definitely thought of exactly that and would love to - just a matter of finding the time. On each of these topics there is a lot more to say and different scenarios to cover. Just have to find the right life balance of things that pay enough to eat and things that are fun to do but would make me homeless if I spent too much time on them. :)

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Waleed on Feb 02, 2011 23:50

    Not sure, if you still follow up this post, but anyway, I am a little bit confused as I try to implement the approach introduced here.

    I have my viewmodel as follows:

    public EntityQuery<user> Users { get; set; }
            GLDomainContext _context = new GLDomainContext();
              
            public LogonViewModel()
            {
                  
                Users = _context.GetUsersQuery();
                LoadOperation<user> loadOp = _context.Load(_context.GetUsersQuery(), 
                                                        new Action<LoadOperation<user>>(OnTasksLoaded),
                                                        null);
            }
            void OnTasksLoaded(LoadOperation<user> lo)
            {
                if (lo.HasError)
                {
                    lo.MarkErrorAsHandled();
                    return;
                }
                this.RaisePropertyChanged(()=> Users);
            }

    I am using PRISM (first time) so my viewmodel is implementing the NotificationObject.

    Why I can't get the users to bind back to the grid itemsSource !!

    What am I doing wrong here ...

    Appreciate your feedback

    Waleed

     

     

     

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Feb 03, 2011 00:06

    Hi Waleed,

    The EntityQuery<T> that is returned from the DomainContext is always going to be the same. It is an expression tree that is sent to the server for execution that is used to retrieve the entity collection. It is not the entity collection itself.  What you want is a property of type IEnumerable<User> in your view model that you can point to the Users collection on the DomainContext. Then your view will be indirectly binding to the Users collection on the domain context itself, which will be populated when the Load operation completes. You shouldn't have to raise the change event on the property yourself, because the underlying collection does not get overwritten, it just gets populated (.Add calls) and it will raise CollectionChanged events itself so the view should update.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Waleed on Feb 03, 2011 00:11

    Dear Brian,

    I already added the IEnumerable<user> userE and assigned it to the op.Entities and it works perfect.

    Thanks for your reply indeed

    Waleed

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by acsed on Feb 09, 2011 19:38
    Hi Brian,
    I do not see any "Model" (the first 'M' of 'MVVM') in your implementation. All what the Model is supposed to do (for instance the access to the data) is implemented within your View Model, which is not what is supposed to be done when using the MVVM pattern. In your example, there is a very strong coupling between the DAL and the View Model.
    Please correct me if I'm wrong.
    Thanks for your article
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on Feb 11, 2011 17:00

    Acsed:

    The Model is rarely an explicit thing in MVVM the way the views and view models are. The model is the combination of the business objects (entities), business rules, data access - I like to say the model is everything else besides the views and view models. But what most people focus on as far as the model is concerned are the business objects or domain model itself, which is represented by the entities in a RIA Services application. The combination of the data they contain along with any validation you embed on them through the validation attribute constitutes most of the client side model.

    As far as true data access is concerned, that happens on the server side by necessity in any Silverlight application, whether RIA Services or not. View models are all about containing data, providing it to the view, and manipulating that data in response to user interactions. So they have to get that data somehow. The most common pattern is the repository pattern to insulate the view model from how the data gets into the client, which I did not do here because unfortunately the further back in the stack you bury the RIA Services stuff. the less value you get out of it and the purpose of the article is to show how to use RIA Services, not how to put together the most decoupled client architecture possible. In my real world projects, I often will wrap the RIA domain context in a repository to decouple the view model from the mechanism of getting data into the app if there is some potential of swapping it out.

    But realize that the domain context is a repository itself - it exposes a collection like interface (unfortunately not a true .NET interface that can be mocked, but at least a collection like API). And as I show in a later article, there is at least a means of mocking (albeit complicated) the guts of the domain context, so there is a degree of testability there.

    Anyway, your question leads to a long design discussion that can't be done here and that really has to be done in the context of a given app to be meaningful in terms of picking the right degree of abstraction.

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Jason Wang on Apr 19, 2011 12:18
    Thank you code and guildine of  WCF RIA SERVICE. It's good for me and it gives me a lot of insprite.
  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Tim on May 11, 2011 17:02

    My ViewModels to date have all used ObservableCollections for binding the XAML with.

    What is the best method of working with RIA Services and ObservableCollections.

    Should I

    a) Change the Domain Service to provide ObservableCollections

    b) Convert the data when loading it in the ViewModel (introduces possible continuity issues)

     c)Use a different type of collection for data binding

     

    Thanks,

    Tim

  • -_-

    RE: WCF RIA Services Part 4 - Integrating with the Model-View-ViewModel Pattern


    posted by Brian Noyes on May 12, 2011 02:29

    Tim,

    The point of using ObservableCollection is that it supports INotifyCollectionChanged to keep the UI up to date when you binid to it and the collection changes behind the scenes. The collections exposed by the DomainContext implement that interface as well, so they are just as suitable for data binding or exposing from your ViewModel as an ObservableCollection. If you want a little more decoupling between your view model and the domain context, you will want to look at the preview of SP2 - they are making it so the underlying collections of the domain context are more detachable and support direct data binding a little better.

Add Comment

Login to comment:
  *      *       

From this series