Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 11: The Client-Only World

I have had a great time so far with this series..  I hope you have gotten something out of it as well.  Some readers have asked me if RIA Services is required for the client validation goodness.   Nope, the .NET RIA Services bits are not required… you can do this sort of cool client UI (validation, sorting, filtering, etc) with all client data or data that you got via whatever mechanism.   

So the title is a bit misleading – we are not going to use ANY .NET RIA Services in this section…

image image On the design team for this work, we said we wanted it to be Ice Cubes not Ice Burgs..  that is bits of technology that work really well together and mixed-n-matched.  Rather than a monolithic ice burg that you have to take all or nothing from. 

The hard part of this pattern is getting your data into the Silverlight app…  You’d only really want to use this pattern if you had another good way to get data  in… this demo punts on that problem and just shows in memory data. 

The demo requires (all 100% free and always free):

  1. VS2008 SP1

  2. Silverlight 3 RTM

  3. .NET RIA Services July ’09 Preview <— Not actually required for this demo!  But good to have none the less 😉

Also, download the full demo files and check out the running application.

For this demo, we will look only at the client side.. we are getting no data from the server.  The only thing that comes from the server is an HTML page containing the XAP.  This could be hosted on any web server.. 

On the client, I created a  DataAccess folder and defined my SuperEmployee class in there

public  class SuperEmployee : INotifyPropertyChanged, IEditableObject
    private SuperEmployee cache; 
    private int _employeeID;
    private string _gender;
    private Nullable<int> _issues;
    private Nullable<DateTime> _lastEdit;
    private string _name;
    private string _origin;
    private string _publishers;
    private string _sites;
    private static int empIDCt = 0;
    public SuperEmployee()
        this._employeeID = empIDCt++;

Notice it implements a couple of interfaces to help with the binding… we will look at how those are implemented shortly.    In the constructor, i auto increment the employeeID key.. you can do that however you want of course.

Then for each property we implement the following pattern:

        public int EmployeeID
                return this._employeeID;
                if ((this._employeeID != value))
                    ValidationContext context = new ValidationContext(this, null, null);
                    context.MemberName = “EmployeeID”;
                    Validator.ValidateProperty(value, context);
                    this._employeeID = value;

Notice all the fun happens in the setter.  There, we create a ValidationContext and call ValidateProperty.. that is the thing that goes and looks at the attributes on this member and does the validation work.  It throws an exception  when there is a problem which is how Silverlight client deals with validation issues.   Notice here we are also raising property changed notifications, again to help with binding.  Each one of the properties looks just like this..

Then, for DataForm support, we need to implement IEditableObject  basically supporting cancelablity.  I choose a pretty simple pattern for this.  Notice I just save off the value on Begin edit and copy it back if CancelEdit is called. 

public void BeginEdit()
     this.cache = new SuperEmployee();
     this.cache.EmployeeID = this.EmployeeID;
     this.cache.Gender = this.Gender;
     this.cache.Issues = this.Issues;
     this.cache.LastEdit = this.LastEdit;
     this.cache.Name = this.Name;
     this.cache.Origin = this.Origin;
     this.cache.Publishers = this.Publishers;
     this.cache.Sites = this.Sites;
 public void CancelEdit()
     this.EmployeeID = this.cache.EmployeeID;
     this.Gender = this.cache.Gender;
     this.Issues = this.cache.Issues;
     this.LastEdit = this.cache.LastEdit;
     this.Name = this.cache.Name;
     this.Origin = this.cache.Origin;
     this.Publishers = this.cache.Publishers;
     this.Publishers = this.cache.Publishers;
     this.Sites = this.cache.Sites;
     this.cache = null;
 public void EndEdit()
     this.cache = null;

Then I just raise my property change notifications

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propName)
    if (this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propName));

Next, we need a whole bunch of these SuperEmployees… For this demo, I just create them from in memory objects. You’d need to think about how you are going to get your data.. WCF services?  Astroria? Generic REST?  RIA Services of course 😉  Anyway, here is what that looks like in the demo:

public class SuperEmployeeList
    List<SuperEmployee> list = new List<SuperEmployee>()
        new SuperEmployee() {
        Name = “Alfred”,
        Sites=“first appears in Batman #16”},
        new SuperEmployee() {
        Name = “Alfred E. Neuman”,
        Sites=“first appears in MAD #21”},

Then I just add a few methods to help me access the this data from the UI:

public string OrginFilter { get; set; }
public IEnumerable<SuperEmployee> GetEmployees()
    if (OrginFilter != null && OrginFilter != String.Empty)
        return list.Where(emp=>emp.Origin.Contains(OrginFilter)).ToArray();
    else return list.ToArray();

The UI looks pretty much like we have seen it before, but I set the data source in code to make it a little more clear..

SuperEmployeeList Context = new SuperEmployeeList();
public Home()
void LoadData()
    PagedCollectionView pcv = new PagedCollectionView(Context.GetEmployees());
    dataGrid1.ItemsSource = pcv;
    pager1.Source = pcv;
    originFilterBox.ItemsSource = Context.GetOrigins();

Those are really the highlights..  Here is what you end up getting.. exactly what we have seen before! Validation works, sorting, filtering, etc.  All client side. 


Comments (14)

  1. Darick says:

    Quick question:  On the running application, when you navigate to one of the other pages (about, my page) and then navigate back to Home, it doesn’t reload the page (say you click on a different person than the first person, that person is still selected when you navigate back to the Home page).  In my application and in the source code, it reloads the page and reloads the data.  How do you get it to not reload the page?

    Hopefully my question makes sense.



  2. Peter Wone says:

    Phenomenal work, I have never seen such a significant framework so cleanly implemented.

    One thing that seems to elude me though – subtleties of more advanced binding. For example, a very important scenario is the handling of foreign keys that are essentially enumerations. These tables generally have two columns: Id and Name.

    I cannot for the life of me figure this one out. I would have expected it to look like this (but this doesn’t work so obviously it’s not right).

               <data:DataGridTemplateColumn Header="Party">




                     Style="{StaticResource ContentTextStyle}"

                     Text="{Binding Data.Name, ElementName=ddsParty}"                    







                     SelectedItem="{Binding Id, Mode=TwoWay}"

                     ItemsSource="{Binding Data, ElementName=ddsParty}"

                     DisplayMemberPath="Name" />




  3. Peter Wone says:

    I should add that ddsParty is a DomainDataSource declared in XAML and it works fine when I bind a datagid to it. The snippet I supplied is part of a datagrid bound to another DDS declared in XAML using this clause

      ItemsSource="{Binding Data, ElementName=ddsTransfer}"

  4. Hi Sir,

    Will this be working for Master-Detail grids also. Please let me know the details.



  5. Eric L says:


    We have very much appreciated this series.  One other RIA question:

    If you use RIA (July 09) for a web application does it REQUIRE that the user installs Silverlight 3?

    I’m asking because we are thinking of developing a web application with both free and paid-for subscribers using ASP .Net with Silverlight 3 "island" views.  If only paid-for subscribers are given access to the Silverlight "islands" would free subscribers have to install Silverlight 3 anyways if we use RIA services?

    We’ve tried but it seems to prompt for Silverlight 3 even on ASP .Net-only entry page if not installed.

  6. Two questions:

    1. Any suggestions as to how to take the tedium out of implementing INotifyPropertyChanged? In my experience, this pattern tends to frequently introduce trivial copy/paste bugs. Validation makes it that much worse.

    2. Why are you calling .ToArray() in GetEmployees() ?

    Thank you!

  7. ben says:

    Michael – unit testing would help out with the copy / paste bugs for the property changed / validation stuff

  8. Yes, it would, no argument. I can try and think of more ways to kill productivity, doing pointless, menial … work, I am sure I can.  😉

  9. BradA says:

    Michael – Yea — i get your point.. if you use a Framework such as .NET RIA Services you don’t have the sort of plumbing code to deal with..  I can see other frameworks and code generators following this pattern… In fact I am pretty sure DevForce does that with their recent Silverlight release..

  10. BradA says:

    Eric L – RIA Services does not require Silverlight on the client…  Take a look at the Sitemap.aspx page in my example:

    No Silverlight required at all on the client to view..

  11. Seriously though, yes, unit testing would help, but I would rather avoid this time sink altogether, if possible. Just like we went from explicit getters and setters to implicit ones, I would love to see syntactic sugar to help implement INotifyPropertyChanged.

  12. Jason Gray says:

    As a Silverlight beginner, I have been really benefiting from this series, but I now have an issue that has stumped me. I had been basing a new project around the WCF model from part 8 of this series, and everything was working fine. However, to better suit our needs, I am beginning down the socket road to to incorporate pushing data to the Silverlight client. One part of this is having the small data set kept in memory on the client, which can then be filtered/sorted, etc locally.

    This "Client-Only" version of the series seems the perfect model for this, and Brad’s comments suggest that I can use RIA services to populate the data on the client. Well when I use a DomainDataSource, I can successfully bind the grid using the DomainContext (RIA/WCF service), but when trying to use the same service to populate a typed list, I get nothing. It appears the service is never called, and from SQL Profiler, I never see a DB call being made.

    I am using the following to try and populate the context:

    LoadDomainContext cxt = new oadDomainContext();


    But after running these statements, the DB is still not hit. Hopefully, I am just being a bonehead and missing something. Ideas?

  13. Jason Gray says:

    As is often the case, I have answered my own question. I was missing the asynchronous aspect of my RIA service. I replaced:

    LoadDomainContext cxt = new loadDomainContext();


    with this:

    LoadDomainContext cxt = new LoadDomainContext();

               cxt.Load(cxt.GetAvailableLoadsQuery(), AvailableLoadsQueryReturn,null);

    private void AvailableLoadsQueryReturn(LoadOperation<Load> result)


               foreach (Load ld in result.Entities)





  14. Hrushikesh says:


    These are basic things. Please explain some professional things man.

    can you show a real life application use of binding a combo with master table and user select that value and it store id of the in detail table and then  populate the value from the detail table.?