Friday, April 16, 2010

Silverlight 4 using MVVM Pattern, RIA Services and Custom Domain Service

Silverlight Data and Controls Series

Introduction

In this blog I am going to give a quick introduction to using Silverlight 4, RIA Services, MVVM Pattern and Custom Domain Service for persistence. I found lots of blogs available on MVVM but none of the code samples were end-to-end and many got a little “preachy”. Plus none of the examples showed integration with RIA Services. I also chose to use a Custom Domain Service because it seems like all blogs these days are using Entity. In my scenario, it is not possible to use Entity because we have to use existing services that have already been created.

In this blog I will give you a straight up introduction to all of these and get you right to the code.

MVVM Background

If you want to read a decent write up about MVVM please read this - http://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx. I basically three types of classes:

1. Model – These will be the Data Transfer Objects (DTO) that will be defined in the RIA Services.

2. View – These are the Form and User Controls.

3. ViewModel – These are classes that define the binding and event logic and act as a mediator between the Model and View.

If you know anything about MVVM the basic goal is minimize the about of code-behind code in your Silverlight Form and User Control files. I think it a little ridiculous to try to remove all code, and in this solution I have very little, just three lines. There will be times where complex UIs will require code and that just cannot be avoided. However I would try to make sure that all logic that you would traditionally put in event handlers be moved to ModelView objects.

I think that is about as simple as you make it, now let’s get to some code.

Project Creation

Just create a Silverlight application and enable RIA Services when creating the project.

The Solution

The solution is pretty basic. As you will see there is the RIA Service project and the Silverlight project. Take note that I have created a folder called Model in the RIA Services project. This is where all the DTO objects should be placed. In the Silverlight project there is a ViewModel and View folders were respective files will be placed. This is mostly done for organization purposes.

Untitled

The Form

The form that has been created is very simple. It is actually made up of two user controls and a single form. The goal of this is to demonstrate how easy it is to get this wired up using the MVVM pattern with Silverlight and RIA Services; the goal is not make a full application. The user will be able to select an item in the grid which will populate the textboxes at the bottom. Pressing the save button will save all the employee changes back to the Custom Domain Service.

Untitled2

Employee DTO

Here is the Employee DTO object. It is real basic as the important thing as we will soon learn is how to get all this wired up.

namespace MVVM.Web.Model
{
public class EmployeeDTO
{
[System.ComponentModel.DataAnnotations.Key]
public int ID { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public DateTime HireDate { get; set; }

public int Title { get; set; }
}
}


Domain Service

The following is the Employee Domain Service which will return a list of employees and also support insert, update and delete operations. All you will need to do is put in code within these stubs to call whatever existing service you have to persist the data. For the query method, I just return a hard coded list of Employee DTO objects.

Note that RIA Domain Service handles all the plumbing of calling the correct method based on the state of the object. I was literally blown away with how little work I now need to do.

namespace MVVM.Web.Service
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;

using Model;

// TODO: Create methods containing your application logic.
[EnableClientAccess()]
public class EmployeeDomainService : DomainService
{

public List<EmployeeDTO> GetEmployees() {
List<EmployeeDTO> employees = new List<EmployeeDTO>();

EmployeeDTO employee = new EmployeeDTO();
employee.ID = 1;
employee.FirstName = "Jason";
employee.LastName = "Apergis";
employees.Add(employee);

employee = new EmployeeDTO();
employee.ID = 2;
employee.FirstName = "Ethan";
employee.LastName = "Apergis";
employees.Add(employee);

employee = new EmployeeDTO();
employee.ID = 3;
employee.FirstName = "Caroline";
employee.LastName = "Apergis";
employees.Add(employee);

return employees;
}

private static int count = 10;
public void InsertEmployeeDTO(EmployeeDTO employee) {
//Code to insert employee
employee.ID = count++;
}

public void UpdateEmployeeDTO(EmployeeDTO employee)
{
//Code to update employee
}

public void DeleteEmployeeDTO(EmployeeDTO employee)
{
//Code to delete employee
}
}
}


Employee View Model

The following is the employee view model there are several things going on.

  • In the constructor we create an instance of the Domain Service Context and then load up all the employees.
  • There is a property called SelectedEmployee which is used to keep track of what Employee is selected.
  • Next there is a property that returns a list of employees so that they can be bound to the grid.
  • There is a method to handle creation and deletion of employee objects.
  • There is a save method that called the Domain Service Context SubmitChanges method. This will push all the changes back to the RIA Services.
  • Finally there are methods used for return an object that implements the ICommand interface. They are used to wire up a click event of a button without having to put code into the code behinds.

using MVVM.Web;
using MVVM.Web.Model;
using MVVM.Web.Service;

namespace MVVM.ViewModel
{
public class EmployeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private EmployeeDomainContext _context = null;
private EmployeeDTO _selectedEmployee = null;

public EmployeeViewModel()
{
_context = new EmployeeDomainContext();
_context.Load(_context.GetEmployeesQuery());
}

public EmployeeDTO SelectedEmployee
{
get
{
return _selectedEmployee;
}
set
{
_selectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}

public EntitySet<EmployeeDTO> Employees
{
get
{
return _context.EmployeeDTOs;
}
}

public ICommand SaveCommand
{
get
{
return new SaveCommand(this);
}
}

public void Save()
{
if (_context.HasChanges)
{
_context.SubmitChanges();
RaisePropertyChanged("Employees");
}
}

public ICommand InsertCommand
{
get
{
return new InsertCommand(this);
}
}

public void Insert() {
EmployeeDTO employee = new EmployeeDTO();
employee.ID = 0;

_context.EmployeeDTOs.Add(employee);
RaisePropertyChanged("Employees");
}

public ICommand DeleteCommand
{
get
{
return new DeleteCommand(this);
}
}

public void Delete() {
_context.EmployeeDTOs.Remove(SelectedEmployee);
RaisePropertyChanged("Employees");
}

private void RaisePropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
}

Save, Insert and Delete Commands

Here is the code of the class that implements the ICommand object to create a new employee object. This class has a reference to the View Model and will call the appropriate method.

namespace MVVM.ViewModel
{
public class DeleteCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;

public DeleteCommand(EmployeeViewModel evm)
{
_evm = evm;
}

public bool CanExecute(object parameter)
{
return true;
}

public void Execute(object parameter)
{
_evm.Delete();
}
}
}

namespace MVVM.ViewModel
{
public class InsertCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;

public InsertCommand(EmployeeViewModel evm)
{
_evm = evm;
}

public bool CanExecute(object parameter)
{
return true;
}

public void Execute(object parameter)
{
_evm.Insert();
}
}
}

namespace MVVM.ViewModel
{
public class SaveCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;

public SaveCommand(EmployeeViewModel evm)
{
_evm = evm;
}

public bool CanExecute(object parameter)
{
return true;
}

public void Execute(object parameter)
{
_evm.Save();
}
}
}

Personally I think this is a little overboard, and if you just want to call the View Model method directly from an event handler in the code behind, that is really not that bad. There is really is very little code in the code behind at this point.

Employee Grid Control

Below is the xaml code for the Employee Grid Control that I created. Just take note of the ItemsSource and SelectedItem attributes and how they bind to the EmployeeViewModel properties. Also note that Command attribute on both of the buttons and how the bind to the command classes we created.

<UserControl x:Class="MVVM.View.EmployeeView"
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"
mc:Ignorable="d"
d:DesignHeight="210" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid AutoGenerateColumns="True" Name="grdEmployees"
Height="168" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="400"
ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee, Mode=TwoWay}"/>
<Button Content="Insert" Height="23" HorizontalAlignment="Left" Margin="232,176,0,0"
Name="btnInsert" VerticalAlignment="Top" Width="75"
Command="{Binding InsertCommand}"/>
<Button Content="Delete" Height="23" HorizontalAlignment="Left" Margin="313,176,0,0"
Name="btnDelete" VerticalAlignment="Top" Width="75"
Command="{Binding DeleteCommand}"/>
</Grid>
</UserControl>

Employee Detail Control

This is the second user control that will populate based on the select item in the grid in the other user control. The following is the xaml code for that control. Notice that the textboxes bind to the SelectedEmployee.* property of the EmployeeViewModel.

<UserControl x:Class="MVVM.View.UpdateView"
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"
mc:Ignorable="d"
d:DesignHeight="48" d:DesignWidth="347">

<Grid x:Name="LayoutRoot" Background="White">
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="txtFirstName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.FirstName, Mode=TwoWay}"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="138,12,0,0"
Name="txtLastName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.LastName, Mode=TwoWay}"/>
<Button Content="Save" Height="23" HorizontalAlignment="Left"
Margin="264,12,0,0" Name="btnSave" VerticalAlignment="Top"
Width="75" Command="{Binding SaveCommand}"/>
</Grid>
</UserControl>

Form XAML

Next we have the xaml code for the main form that has the two user controls that we have created. All we had to do was add the xmlns:view="clr-namespace:MVVM.View" namespace.

<UserControl x:Class="MVVM.MainPage"
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:view="clr-namespace:MVVM.View"
mc:Ignorable="d"
d:DesignHeight="278" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<view:EmployeeView x:Name="vwEmployee" Height="207" VerticalAlignment="Top" HorizontalAlignment="Left" Width="400" />
<view:UpdateView x:Name="vwUpdate" Height="45" VerticalAlignment="Top" HorizontalAlignment="Left" Width="354" Margin="23,221,0,0" />
</Grid>
</UserControl>

Form Code Behind

Finally we have three lines of code to create the ViewModel object and then set it as the DataContext to both of the controls.

namespace MVVM
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();

EmployeeViewModel emv = new EmployeeViewModel();
vwEmployee.DataContext = emv;
vwUpdate.DataContext = emv;
}
}
}

Summary

That is about the quickest introduction I can provide to using MVVM with RIA Services and a Custom Domain Service.

54 comments:

C.J. said...

Finally, a vanilla example with a custom domain service...thank you! (Can you also post the code? I copied/pasted and got it to work, but that would save some time.)

Jason Apergis said...

CJ,

Appreciate the feedback. I wrote this because everyone is so busy telling you about Entity, that no one just gave me something basic to start from if you have to do something custom. Since when is the entire stack all SQL server?

As for getting the solution up there, it is buried down in one of my hundreds of VPCs. I know the tool I use for formatting my code makes it a little difficult to copy out.

Thanks,
Jason

Veronica said...

Thank you so much for this elegant and simple solution - I have been searching for something like for ages! I am encountering a small problem, though: I get an assembly error with the EmployeeDomainContext. Is it auto-generated somehow, or where do you define it? Thanks!

Jason Apergis said...

Thanks for the feedback.

Yes, the code for the Context class is generated. The name of the context class is based on the name of the RIA Service.

To find the generated code of the RIA Service Context class >> show hidden files >> open the Generated_Code folder >> and you will find a class called XXX.g.cs. That is where all of the generated proxy code to the RIA Service resides.

Thanks,
Jason

2Ton said...

Thankyou so much, this is EXACTLY what i've been searching for! I was able to get it all up and running with my own ORM Framework and SQL database.

Only thing i can't work out is how to automatically update a field in the grid with a database generated value e.g. a GUID or Identity ID? Do you know how I might do this?

Thanks

Stephen

Jason Apergis said...

2Ton,

I have to moderate my comments otherwise I get tons of spam.

There are several ways you can achieve what you need. My blog shows the simple approach.

In this example, in the insert method of the domain service, I have a static variable that is acting like a unique id being created off a database table. When Context.SubmitChanges is called, the RIA insert method will iterate that number and set it back into the domain object. The silverlight app will then have the ID. The one challenge of this approach is that you will need to generate temp ids in the silverlight application until SubmitChanges is called and then reset the IDs correctly.

This example is POC code that I did - son it is not perfect.

In the production application we built our solution was a little more involved. What we eventually did was write CreateXXX RIA Service methods that would create a domain object pre-populated with a new ID generated off the Oracle database we were integrating with. Then the ID would show immediately on the Silverlight screen. The ramification of doing this is the Insert RIA methods would never be called because the object state is marked for update since it was created on the RIA side. To solve that problem, in our Update service methods we would check to see if the ID of the object was currently in the table. If it was not, we would insert, else we would update.

Jason

hyojung said...

Thank you for your detail explanation.
BTW, what if I need to get only some customers? In that case, do I need to create another command class?
If so, don't you think there are too many classes for fetch customers?
Thanks

mozam said...

Dear sir,
Excellent Post. Can I have the Source Code pls?

if yes pls send me mojamcpds@hotmail.com

thanks in advance
Mojam

Jason Apergis said...

Mojam,

Thanks. You are not the first to ask but I have the source on one of my hundreds of VMs and not easy to locate at this point. Given all the code is on the blog, you should be to build whatever you need.

Thanks,
Jason

Mia said...

I am getting the all to familiar Client.DomainOperationException:Load operation failed for query 'GetEmployees'. any ideas on how to resolve this?

Mia said...

By the way, the error with the domain load operation failed is failing on my development box (cassini).

Mia said...

Running WCF trade, the error was "The service '/ClientBin/MVVM-Web-Service-EmployeeDomainService.svc' does not exist." After much googling I came upon an article at http://betaforums.silverlight.net/forums/p/194480/452656.aspx#452656.

My web config had very little in it. I had to add the


and the for the error to go away. This is just on my local box. I am not even sure what others I will get when pushd to production.

Jason Apergis said...

MIA - I am not totally sure I understand your issue.

Jason Apergis said...

MIA - I am not totally sure I understand your issue.

Mia said...

Jason, I didn't realize blogspot's comment system strips out html. Basically when I create a Silverlight 4 application with RIA Services, nothing about http modules or serviceHostingEnvironment are inserted into the web config. Without these, I received the "'/ClientBin/MVVM-Web-Service-EmployeeDomainService.svc' does not exist."

I had two questions for you.

1)I noticed several example on the internet where the Service class inherits from DomainContext but your example inherits from DomainService? Is there any difference?

2)I have a text box that a user has to put in a Customer Name and then from there, I can return a list of products for that customer and bind to the datagrid. How do I capture that textbox value from the ViewModel?

By the way, your example app was the best place for me to get up an running on learning RIA Services with Silverlight. Thank you very much.

Mia said...

Disregard question #2, I figured out how to do it. I created a public property in my ViewModel and then bound that property to the text box. Sorry for commenting so much. I felt inspired to get this working!

Jason Apergis said...

Mia,

When I add domain services to the RIA Services project, I simply go Add >> New Item >> select Domain Service class.

Jason

Uwe said...

Quite nice, but a (newbies) question:
After pressing the "insert Button" a new epmloye was added, but without FirstName + LastName. Did I make an
(copy&paste-) Mistake.

Jason Apergis said...

Thanks.

The insert method on the ViewModel only creates the object, it does not assign a first or last name. The user needs to type that in...

Jason

Devc7 said...

Hi Mia,

I am also getting this error, which you got earlier.

Client.DomainOperationException:Load operation failed for query 'GetEmployees'.

You wrote it as
"My web config had very little in it. I had to add the


and the for the error to go away"

There is nothing on the blog after "add the" and "and the".
What did you do to get rid of that error?

Devc7 said...

I got it.
i had to add httpModules in the system.web tag. And it worked for me.

I have a confusion here. This will work for one employee as a table.
What happens when you have loads of table.
In that case how do you implement MVVM. Do i have to create seperate ViewModel Classes for each of the modules i have in my application?

I worked on SL3 with the old RIA services where i created 1 main class for ViewModel and it has all the functions with different names like deleteEmp, AddEmp, DProd, UpdProd etc. etc. But i didnt use the ICommand approach. Also we had a static object for DomainContext class object.

So i am wondering if I assign a SaveCommand, UpdateCommand for buttons for each View for each Module in my application, how Do i write the whole thing in 1 class which in this case is EmployeeViewModel.cs
In that case I will have to create multiple ViewModel Classes for each and every step. And in case of screens where there are multiple tables involved, there might be duplication of code.

Is there any way I can get it done?

Jason Apergis said...

The ICommand implementaiton is not needed - and can become annoying with time because it is not really possible to write up many of the other UI events in that manner. I am not a Silverlight purest. I would recommend just creating event handlers in your View which call the ViewModel where all the core logic is.

As for your second question, good Object Orientated patterns can be used. I had a similar case. What I did was this. I had View A, View B and View C. The I ViewModel A, B and C which have spepcific logic for each View. Then I create a ViewModel Base which View A, B and C inherited from. Then you can create base methods and override them on the child classes. I actualy had a significantly complex inheritance hierachy but that should get you started.

Jason

Devc7 said...

Thanks a lot....
And sorry i could not response back sooner. I just implemented it over the weekend and its working awesome.

I still kept the ICommand implementation and made the functions as virtual. Also i created seperate ViewModel Classes which inherits from the main ViewModel class.
I override the functions and the main properties in these derived class. The best thing is that i dont have to write any extra event handling in the XAML for button clicks. So i added more commands :) to the code like LoadData, Serialize (to XML).
Cool...

Thank you very much.
Tussi Great Ho. (in indian language it means You are great)

Happy Coding.

Kimmy See said...

Good day,

In creating the Employee View Model, how do we add reference to the RIA services project for as follows:
using MVVM.Web;
using MVVM.Web.Model;
using MVVM.Web.Service;?

Visual Studio 2010 can't seem to find these references. We're using Silverlight 4 SDK by the way.

We've included a screenshot for your convenience: http://img217.imageshack.us/img217/5391/screenshotpii.png

Thanks and best regards.

Jason Apergis said...

Kimmy - the screenshot link is not working. However I bet your problem is you changed the name of the projects I used in this demonstration. The projected RIA code namespace is based on the RIA project name. In this case I used MVVM.web

Kimmy See said...

Hello,

We used exactly the same namespace as your tutorial. Nevertheless, regarding our previous problem, we've already fixed it, well, magically... I just freshly formatted my laptop and redid your tutorial, and the problem magically gone, however, we encountered another problem:
The type or namespace name 'EntitySet' could not be found (are you missing a using directive or an assembly reference?)

We've tried to google it, and found out that EntitySet belongs to the System.Data.Linq.dll assembly, however we're not able to add it as a reference in our Silverlight Project. As we try to add it, the following error message appears:
You can't add a reference to System.Data.Linq.dll as it was not built against the Silverlight runtime. Silverlight projects will only work with Silverlight assemblies.

We've attached our project solution using another filehost, please try to download and check it if you don't mind. Here's the link: http://www.mediafire.com/?ak96a808db556au

Sorry to trouble you, and thank you for your quick response. Please and thank you. Best regards.

Jason Apergis said...

Kimmy,

Sorry - I do not have the bandwidth to go through your solution. I can see that you are new to Silverlight development.

First - it is not possible to directly reference .NET DLLs in the Silverlight runtime. For instance if you ever build a custom C# project library you cannot reference it in a Silverlight project.

Second - You need to work with generic lists. Read through other blogs in this series and that should hopefully help you.

Jason

Attenuating Thoughts said...

EntitySet comes from System.ServiceModel.DomainServices.Client namespace.

Kimmy See said...

Thank you, Jason and Attenuation Thoughts. I really appreciate your kind responses and explanations. Yes, we're new to Silverlight development. We're working on it for our thesis. Thanks once again.. ^-^

Kimmy See said...

I finally got it to work last night, thanks for all your help and patience.. ^-^

Mia said...

Great article, I come back here everytime for a refresher. I have a question as to why my button bound to a command is not firing.

I have a ViewModelBase class that has the NotifyPropertyChanged method.

I have a ViewModelCommand generic class for CanExecute, Execute, and OnCanExecuteChanged.

To use this command in my viewmodel, I create a public property, in the viewmodel, of this ViewModelCommand.

And in my button control (in xaml), I wire up the command property in the UI to the command: Command="{Binding SearchCommand}"


When I click on the button, it does not fire.

Am I leaving anything out?

Jason Apergis said...

Mia,

It is really tough to tell. Please just retrace how I have it here in the blog.

Jason

Devc7 said...

The only 2 things that could be missing are
public ICommand TestCommand
{
get
{
return new TestCommand(this);
}
}


AND

the view or page or dataform (.DataContext) equals to the your ViewModel class object.

Mia said...

Thanks, I figured out why my commands were not firing. I am writing an OOB app.

In my EmployeeView.xaml.cs, I have set the LayoutRoot.DataContext = Deployment.Current.OutOfBrowserSettings per: http://msdn.microsoft.com/en-us/library/dd833066(VS.95).aspx

but in my MainPage.xaml.cs, I still do this:
EmployeeViewModel emv = new EmployeeViewModel();
vwEmployee.DataContext = emv;

Is setting the DataContext =Deployment.Current.OutOfBrowserSettings in my VIEW causing my EmployeeViewModel to not bind properly to the view.

Have you come across this?

jim said...

Hi Jason,
Thanks for sharing your work with us. I'm a newbie to silverlight, MVVM, & RIA. Finally I found one that I can copy from and it works.

When I clicked on any of the buttons, I was getting "This ENtitySet of type MVVM.Web.Models.EmployeeDTO' does not support the Add operation. Are you able to figure where it goes wrong? Thanks.

Jason Apergis said...

That I have not run up against. I would be highly surprised that running out of browser would affect what you experiencing - but I have been wrong before :-)

Jason

Jason Apergis said...

Jim,

Thank you for the feedback. This series has turned out to be very helpful to lots of people.

Going from memory, it seems like the RIA Service insert method may not be working. But if it compiles, the method is obviously being gerenated on the Silverlight application side.

Maybe try adding the [Insert], [Update] and [Delete] attributes on top of the RIA Service method definitions.

Thanks,
Jason

Devc7 said...

Hi Jason,

First of all thanks for this post... Because of this post, my personal website is moving forward.

I have 2 questions regarding RIA and MVVM pattern

1. Is there any material available on internet where they are calling Stored Procs using RIA services and most importantly using LINQ.
Where ever i saw, the answers are not really related to the question.

2. In my ModelView how do i tell the view that some data-fetching is complete.
This question is a little wierd, because databinding takes care of all that.
But in my case i have a recursive table with Parent-child relationship and Tree control is not getting filled up with the objects directly also LINQ does not make recursive calls. So i created a SQL View, returned the class(with all the variables with respect to the output columns of the SQL View) also i created our old age friend (user defined Entity objects and LIST and Collections with Generics) and returns the objects to the viewmodel.
The viewModel fills up the data, but TreeView has to be added manually. But it takes time to load the data. after the LoadOperation is done, i have to click another Button ( I called it as a 'Refresh Data' )to take the data and load it to the treeview control.
So is there any way we can tell the view that ok, the data is filled now, so take it and put it in the control.

Jason Apergis said...

Devc7,

1 - I do not have a reference handy but LINQ cannot called a SP. The Entity Framework work can. Note you can write code in these RIA Services to call stored procedures.

2 - Read this blog post wich is part of this series. This shows how to create a call back when a RIA method has completed - http://www.astaticstate.com/2010/08/silverlight-ria-data-validation-best.html

praveen said...

Hi

Really its a good post, perhaps it would be better if you provide code to download

Thank You
Praveen

Jason Apergis said...

Praveen,

Thanks for the feedback.

As for providing the code - I tend not do that. First I do not have the code anymore :-) Two I do not have the time to support it. Three I like to see people learn and figure things out instead of just copying and pasting.

Thanks,
Jason

Subha said...

Hi Jason,

If we were to add validations to the client, which layer we need to put it in? Is it View Model? Could you please explain with one example?

thanks,
Subha

Jason Apergis said...

Subha,

Your answer is in the last part of this Silverlight series.

http://www.astaticstate.com/2010/08/silverlight-ria-data-validation-best.html

Thanks,
Jason

Philip said...

The first article I've read that actually explains MVVM in nice simple terms. I can't credit you enough.

markus said...

Many thanks, this is exactly what I was looking for!!!

One question, say I dropped a calendar control on the "EmployeeView" and I wanted only employees hired after the date clicked. I am new to MVVM so I was wondering what the best method was.

-Markus

Jason Apergis said...

Markus - In this series I wrote about data validation. Please read this and it should point you in right direction - http://www.astaticstate.com/2010/08/silverlight-ria-data-validation-best.html

markus said...

Hey Jason,

I think you may have misunderstood my question or I didn't catch the relationship with the link.

I added a calendar control on the employee view. When the user changes the date I want to only see employees hired after that date (and I want the filtering done in the server). What is the best way to do this using the MVVM pattern?

Jason Apergis said...

Markus - sorry for the delay response on your second question. At a high level you would look an event to the calendar control and then refresh the source on the grid. Sorry I do not have the code sitting around anymore and I do not have the time to type it up.

Jason

Pedro Carvalho said...

Jason Hello my name is Pedro Carvalho, I am Brazilian, and I'm currently studying Siverlight, I did everything according to your blog is more to run the system is giving this error Client.DomainOperationException: Load operation failed for query 'GetEmployees', you said you added where the httpModules devevo add this command. In web.config?. You could provide this source code?

Jason Apergis said...

Pedro - Unfortunately I do not have enough information and I can tell you that if you follow the instructions this sample will work.

I know this has been a very popular series on Silverlight but I do not have the source code anymore. It on some old virtual machine that I have long lost by now.

Phillip Knezevich said...

This is an excellent simple easy-to-use demo.

I have scoured hours on the web for help and nobody has explained this as well as you have. Well done.

Jason Apergis said...

Phillip - I am glad this hit the mark.

Jason

Ivan Maric said...

"I am getting the all to familiar Client.DomainOperationException:Load operation failed for query 'GetEmployees'. any ideas on how to resolve this?"

was probably a consequence of adding domain service class in a web project manually... try right click on a web project, add new item, web category, domain service class... this should fill the web.config file appropriately...

btw, very nice post :)))))))

Jason Apergis said...

Ivan,

Thanks for the feedback. I have not messed with this in a like two years. I am totally rusty - sorry I could not be more helpful...

Thanks,
Jason