0% found this document useful (0 votes)
282 views19 pages

10 - Silver Light Patterns - Using MVVM

The document describes converting a Silverlight application to use the Model-View-ViewModel (MVVM) pattern. It involves creating a service agent class to handle calls to a WCF service from the ViewModel. In Exercise 1, an interface and class are created called CustomersServiceAgent that implements the interface and makes calls to the WCF service by creating a service client and subscribing to async events. This separates the service access logic from the ViewModel.

Uploaded by

Avinash Pathak
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
282 views19 pages

10 - Silver Light Patterns - Using MVVM

The document describes converting a Silverlight application to use the Model-View-ViewModel (MVVM) pattern. It involves creating a service agent class to handle calls to a WCF service from the ViewModel. In Exercise 1, an interface and class are created called CustomersServiceAgent that implements the interface and makes calls to the WCF service by creating a service client and subscribing to async events. This separates the service access logic from the ViewModel.

Uploaded by

Avinash Pathak
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

Building Business Applications in Silverlight 4

Hands-On Lab
Building Applications in Silverlight 4
Using the MVVM Pattern in Silverlight
Applications

MVVM 1|Page
Building Business Applications in Silverlight 4

Contents

Lab 10: Using the MVVM Pattern in Silverlight Applications.......................................................................3


Exercise 1: Creating a Service Agent Class...................................................................................................6
Exercise 2: Creating a ViewModel Class.....................................................................................................10
Exercise 3: Handling Commands and Binding to a ViewModel..................................................................15
Summary...................................................................................................................................................19

MVVM 2|Page
Building Business Applications in Silverlight 4

Lab 10: Using the MVVM Pattern in


Silverlight Applications

The Model-View-ViewModel (MVVM) pattern provides a flexible way to build Silverlight applications
that promotes code re-use, simplifies maintenance and supports testing. The pattern consists of three
different components including the Model (entities and code on the server), the View (the Silverlight
screens) and the ViewModel (the glue between the Model and the View). An example of the how the
Model, View and ViewModel components relate to each other is shown next:

Figure 1
The MVVM Pattern
In this lab exercise you'll learn how to migrate an existing Silverlight application that uses code-behind
files for all of the C# or VB code into a more structured architecture that follows the MVVM pattern.
Topics covered include creating a service agent class to handle calls to a WCF service, creating a
ViewModelBase class, creating a custom ViewModel class and binding a ViewModel to a View
declaratively in XAML. You'll also see how commanding can be used to wire-up events in a View to
methods in a ViewModel. The application that you'll work with in the lab exercises is shown next:

MVVM 3|Page
Building Business Applications in Silverlight 4

Figure 2
Customer Details User Interface

Note: It's recommended that you complete the data binding and WCF labs before starting this lab.
Some of the steps in the lab will provide the code to use while others will explain the task to perform
and let you figure out the code that should be added. If you need help with any of the steps refer to
the lab's Completed folder which contains the finished code.

You Will Benefit from this Lab if


You're interested in building Silverlight applications that take advantage of code re-use,
promote testability and reduce maintenance costs
You'd like to separate your Silverlight application into distinct modules and provide a pattern
that can be followed by a team of developers

MVVM 4|Page
Building Business Applications in Silverlight 4

You're interested in learning the MVVM pattern and the benefits it offers
You Will Learn:
How to convert an existing Silverlight application to use the MVVM pattern
The role of the Model, ViewModel and View in the MVVM pattern
How to create a service agent class and the role it can play in an application to promote code re-
use
How to create a ViewModel class and handle property change notifications
How to bind a ViewModel class to a View
How to communicate between a View and ViewModel using commanding
Business Requirements for the Silverlight application include:
Remove existing code from a Silverlight code-beside file
Create a service agent interface and class to handle calls to a WCF service
Create a ViewModelBase class to handle INotifyPropertyChanged notifications
Create a ViewModel class that derives from ViewModelBase and handles data interactions
Add support for commanding into a ViewModel class
Bind a ViewModel class to a View in XAML
Bind Silverlight controls to ViewModel properties

Estimated Time: 45 minutes

Exercise 1: Creating a Service Agent Class


In this exercise you'll remove existing code in a code-beside file and create a service agent class. The
service agent class will be used to make calls to a WCF service from within a ViewModel class created
later in the lab.

MVVM 5|Page
Building Business Applications in Silverlight 4

1. Open the following Visual Studio 2010 solution file based upon your chosen language.

Language Lab Files Location


C# /MVVMPattern/Starting Point/C#/CustomerViewer.sln

Visual Basic /MVVMPattern/Starting Point/VB/CustomerViewer.sln


2. The following projects are available in the solution:
 CustomerService.Model – Contains entities and data repository classes used to access an
AdventureWorks LT database.
 CustomersService – A WCF service application that exposes entities to various applications.
 SilverlightCustomerViewer – A Silverlight project that consumes data from a WCF service.
 SilverlightCustomerViewer.Web – A website project used to host the
SilverlightCustomerViewer application.

MVVM 6|Page
Building Business Applications in Silverlight 4

Figure 3
Projects in the Solution
3. Right-click CustomerService.svc in the CustomersService project and select View in Browser
from the menu. This will start a local WCF server and show details about the service.

MVVM 7|Page
Building Business Applications in Silverlight 4

4. Back in Visual Studio, right-click SilverlightCustomerViewerTestPage.html in the


SilverlightCustomerViewer.Web project and select View in Browser from the menu. Select
customers from the ComboBox control (note that you may have to wait a moment for the
customers to load the first time the application is run) and notice that the data for each
customer displays in the details area.
5. Back in Visual Studio, open MainPage.xaml.cs located in the SilverlightCustomerViewer
project in the code editor and remove all of the existing code within the MainPage class
except the constructor and the call to InitializeComponent.

Note: All of the functionality in the code-beside file will be moved into a ViewModel class that
you'll create later in this lab.

6. Open MainPage.xaml and remove the Click event handlers defined on the two Button
controls.
7. Right-click on the SilverlightCustomerViewer project and select Add  New Folder. Give the
folder a name of ServiceAgents.
8. Add a new class into the ServiceAgents folder named CustomersServiceAgent.
9. Add the following interface immediately above the class and resolve any missing
namespaces:

Note: Resolve any missing namespaces by right-clicking on an unknown type and then
selecting Resolve in the menu.

C#
public interface ICustomersServiceAgent
{
void GetCustomers(EventHandler<GetCustomersCompletedEventArgs> callback);
void SaveCustomer(Customer cust,
EventHandler<SaveCustomerCompletedEventArgs> callback);
}

Visual Basic
Public Interface ICustomersServiceAgent
Sub GetCustomers(ByVal callback As _
EventHandler(Of GetCustomersCompletedEventArgs))
Sub SaveCustomer(ByVal cust As Customer, _
ByVal callback As EventHandler(Of SaveCustomerCompletedEventArgs))
End Interface

10. Implement the ICustomerService interface on the CustomersServiceAgent class.


11. Add the following field into the CustomersServiceAgent class:

MVVM 8|Page
Building Business Applications in Silverlight 4

C#
CustomerServiceClient _Proxy = new CustomerServiceClient();

Visual Basic
Dim _Proxy as New CustomerServiceClient()

Note: The CustomerServiceClient class is a WCF service proxy class that will be used to
communicate with the remote service to retrieve customer data and perform update and
delete operations.

12. Add the following code in the GetCustomers method to handle calling the WCF service
operation:
C#
_Proxy.GetCustomersCompleted += callback;
_Proxy.GetCustomersAsync();

Visual Basic
AddHandler _Proxy.GetCustomersCompleted, callback
_Proxy.GetCustomersAsync()

13. Add the following code in the SaveCustomer method to handle communicating delete and
update data operations to the WCF service:
C#
_Proxy.SaveCustomerCompleted += callback;
_Proxy.SaveCustomerAsync(cust);

Visual Basic
AddHandler _Proxy.SaveCustomerCompleted, callback
_Proxy.SaveCustomerAsync(cust)

MVVM 9|Page
Building Business Applications in Silverlight 4

Exercise 2: Creating a ViewModel Class


In this exercise you'll create a ViewModelBase class that provides core functionality that can be used by
one or more ViewModel classes. You'll then derive from ViewModelBase and create a ViewModel class
that will be used to retrieve and manipulate customer data used in the MainPage.xaml View.
1. Locate the file named mvvmInpcPropertyCS.snippet (for C#) or
mvvmInpcPropertyVB.snippet (for VB) in the SilverlightCustomerViewer/CodeSnippets
folder.
2. Copy the file for your chosen language to the following location (or use Tools  Code
Snippets Manager in Visual Studio to import it):

Language Lab Files Location


C# Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code
Snippets
Visual Basic Documents\Visual Studio 2010\Code Snippets\Visual Basic\My Code
Snippets

Note: The mvvmInpc snippet will be used to create properties within a ViewModel class later
in this lab. It's one of several snippets available in MVVM Light
(http://mvvmlight.codeplex.com) and has been modified for use in this lab exercise.

3. Right-click on the SilverlightCustomerViewer project and select Add  New Folder. Give the
folder a name of ViewModels.
4. Add a new class into the ViewModels folder named ViewModelBase and mark it as abstract
(C#) or MustInherit (VB).
5. Implement the INotifyPropertyChanged interface on the class and resolve the namespace.

Note: INotifyPropertyChanged is an important interface in Silverlight used by the data binding


engine to notify controls and other objects when a bound property value changes. By
implementing INotifyPropertyChanged on the ViewModelBase class you can write the code
once and re-use it across multiple ViewModel classes. The interface is located in the
System.ComponentModel namespace.

6. Once the interface has been implemented on the ViewModelBase class, add a method
named OnPropertyChanged into ViewModelBase to handle raising the PropertyChanged
event from the INotifyPropertyChanged interface.

MVVM 10 | P a g e
Building Business Applications in Silverlight 4

Note: If you need help with this step please refer to the ViewModelBase class in the lab's
Completed folder. Creating an OnPropertyChanged method was covered in the data binding
lab.

7. Add a new public Boolean property into the ViewModelBase class named IsDesignTime.
8. Add a get block (but no set block) into the property that returns
DesignerProperties.IsInDesignTool as the value. Resolve any namespaces as needed.

Note: When using the MVVM pattern and ViewModel classes it's important to know when
code is executing in a design-time tool such as Visual Studio or Expression Blend and when it's
executing at runtime. When code runs in a design tool network calls will not execute properly
and can error out the designer. The IsDesignTime property will be used to detect where code is
running to ensure that ViewModel classes execute properly at design-time.

9. Add a new class into the ViewModels folder named MainPageViewModel that derives from
ViewModelBase .
10. Add the following properties into MainPageViewModel using the mvvmInpc code snippet
and resolve any missing namespaces as necessary (type mvvmInpc + tab + tab to use the
snippet in C# or mvvminpc + tab to use the snippet in VB):

Property Name Property Type


Customers ObservableCollection of Customer
CurrentCustomer Customer
StatusMessage string

Note: If you need help with creating the properties in this step refer to the
MainPageViewModel class in the lab's Completed folder.

11. Within the CurrentCustomer property's set block add code to set the StatusMessage
property to empty strings (add the code within the existing "if" statement).
12. Add another property named ServiceAgent of type ICustomersServiceAgent and resolve the
namespace (create it as a standard .NET property).
13. Add the following methods into MainPageViewModel to handle retrieving, updating and
deleting customer objects:

Note: The ObjectState parameter used in the following code is automatically created by the
WCF proxy generator when using self-tracking entities in Entity Framework 4. By changing the
object state we can easily track whether delete or update operations should occur for a given
Customer object.

C#

MVVM 11 | P a g e
Building Business Applications in Silverlight 4

private void GetCustomers()


{
ServiceAgent.GetCustomers((s, e) => Customers = e.Result);
}

public void UpdateCustomer()


{
SaveCustomer(ObjectState.Modified);
}

public void DeleteCustomer()


{
SaveCustomer(ObjectState.Deleted);
Customers.Remove(CurrentCustomer);
CurrentCustomer = null;
}

private void SaveCustomer(ObjectState state)


{
CurrentCustomer.ChangeTracker.State = state;
ServiceAgent.SaveCustomer(CurrentCustomer, (s, e) =>
{
StatusMessage = (e.Result.Status) ? "Success!" :
"Unable to complete operation";
});
}

Visual Basic
Private Sub GetCustomers()
ServiceAgent.GetCustomers(Sub(s, e) Customers = e.Result)
End Sub

Public Sub UpdateCustomer()
SaveCustomer(ObjectState.Modified)
End Sub

Public Sub DeleteCustomer()
SaveCustomer(ObjectState.Deleted)
Customers.Remove(CurrentCustomer)
CurrentCustomer = Nothing
End Sub

Private Sub SaveCustomer(ByVal state As ObjectState)
CurrentCustomer.ChangeTracker.State = state
ServiceAgent.SaveCustomer(CurrentCustomer, _
Sub(s, e) StatusMessage = _
     If(e.Result.Status, "Success!", "Unable to complete operation"))
End Sub

MVVM 12 | P a g e
Building Business Applications in Silverlight 4

14. Add the following constructors into MainPageViewModel:


C#
public MainPageViewModel() : this(new CustomersServiceAgent())
{
}

public MainPageViewModel(ICustomersServiceAgent serviceAgent)
{
    if (!IsDesignTime)
    {
        if (serviceAgent != null) ServiceAgent = serviceAgent;
        GetCustomers();

    }
}

Visual Basic
Public Sub New()
Me.New(New CustomersServiceAgent())
End Sub

Public Sub New(ByVal serviceAgent As ICustomersServiceAgent)
If Not IsDesignTime Then
If serviceAgent IsNot Nothing Then
Me.ServiceAgent = serviceAgent
End If
GetCustomers()

End If
End Sub

Note: The first constructor will be called if the ViewModel is instantiated without any
parameters. It passes a new instance of the CustomersServiceAgent object to the second
constructor which assigns it to the ServiceAgent property when not in design mode (note that
instead of hard coding the service agent type it could be injected using a dependency injection
framework). The second constructor accepts any object that implements the
ICustomersServiceAgent interface allowing mock objects to be passed in for the service agent
when testing the ViewModel class. Following this pattern provides a flexible way to work with
different types of service agent objects when the application is running as well as when tests
need to be executed.

15. Ensure that the SilverlightCustomerViewer project compiles before proceeding to the next
exercise.

MVVM 13 | P a g e
Building Business Applications in Silverlight 4

1.

MVVM 14 | P a g e
Building Business Applications in Silverlight 4

Exercise 3: Handling Commands and


Binding to a ViewModel
In this exercise you'll add commanding support into the SilverlightCustomerViewer project.
Commanding allows events triggered in a View such as a Button's Click event to be routed directly to a
ViewModel instance without having to add code in a code-beside file. You'll be introduced to the
ICommand interface as well as a RelayCommand class that will be used within MainPageViewModel to
handle commands. Finally, you'll bind MainPageViewModel to a View using a declarative binding syntax.
1. Open the Commanding/RelayCommand.cs class in the SilverlightCustomerViewer project
and note that it implements ICommand. This interface is required in order for a Silverlight
application to support commanding.

Note: Commanding is the process of forwarding events that occur in the user interface to a
ViewModel object for processing at runtime. The RelayCommand class will be used to wire
properties in a ViewModel to methods that are invoked when any control derived from
ButtonBase is clicked in a View. It satisfies the ICommand interface allowing commanding to be
used in Silverlight MVVM applications.

2. Add the following code into MainPageViewModel to create properties capable of binding to
controls that expose a Command property. Resolve the required namespace.
C#
public RelayCommand UpdateCustomerCommand
{
    get;
    private set;
}

public RelayCommand DeleteCustomerCommand
{
    get;
    private set;
}

Visual Basic
Private _UpdateCustomerCommand As RelayCommand
Public Property UpdateCustomerCommand() As RelayCommand
Get
Return _UpdateCustomerCommand
End Get
Private Set(ByVal value As RelayCommand)
_UpdateCustomerCommand = value
MVVM 15 | P a g e
Building Business Applications in Silverlight 4

End Set
End Property

Private _DeleteCustomerCommand As RelayCommand


Public Property DeleteCustomerCommand() As RelayCommand
Get
Return _DeleteCustomerCommand
End Get
Private Set(ByVal value As RelayCommand)
_DeleteCustomerCommand = value
End Set
End Property

3. Add the following code into MainPageViewModel to handle wiring up the properties
defined in the previous step to methods that will be invoked once a command is executed:
C#
private void WireCommands()
{
    UpdateCustomerCommand = new RelayCommand(UpdateCustomer);
    DeleteCustomerCommand = new RelayCommand(DeleteCustomer);
}

Visual Basic
Private Sub WireCommands()
UpdateCustomerCommand = New RelayCommand(AddressOf UpdateCustomer)

DeleteCustomerCommand = New RelayCommand(AddressOf DeleteCustomer)
End Sub

Note: WireCommands handles associating two RelayCommand properties with methods that
will be invoked as a command is executed in a View. For example, any Button with a
Command property bound to UpdateCustomerCommand will cause the UpdateCustomer
method to be invoked.

4. Add a call to the WireCommands method within MainPageViewModel's second constructor


(add the code immediately under the GetCustomers method call within the constructor).
5. Add code within the CurrentCustomer property's set block to assign the IsEnabled property
of UpdateCustomerCommand and DeleteCustomerCommand to a value of true (add the
code within the existing "if" statement).
6. Open MainPage.xaml and add the following xml namespace definition on the UserControl
element to reference the ViewModels namespace:
XAML
xmlns:viewModels="clr-namespace:SilverlightCustomerViewer.ViewModels"

MVVM 16 | P a g e
Building Business Applications in Silverlight 4

7. Create a UserControl.Resources element within the XAML immediately below the beginning
UserControl element and add the following code into it:
XAML
<viewModels:MainPageViewModel x:Key="ViewModel" />

8. Bind the ViewModel key created in the previous step to the LayoutRoot element's
DataContext property using a StaticResource binding. This will bind a MainPageViewModel
object instance to the DataContext.
XAML
DataContext="{Binding Source={StaticResource ViewModel}}"

9. Build the solution. If you encounter any compilation errors resolve them before continuing.
10. Right-click on the ComboBox control in the designer and select Properties from the menu.
11. Locate the ItemsSource property and click on its Binding value to view the data binding
window. Select Customers from the available Path values as shown next:

Figure 4
Binding Data to the ItemsSource Property
12. Follow the same procedure shown in the previous step to bind the ComboBox control's
SelectedItem property to CurrentCustomer.

Note: You'll need to click on the icon to the right of SelectedItem and then select Apply Data
Binding to access the data binding window.

13. Bind the Text property of each TextBox control to the associated property in
CurrentCustomer.

MVVM 17 | P a g e
Building Business Applications in Silverlight 4

Note: To do this, first clear any existing bindings by selecting the data icon to the right of the
Text property and select Reset Value. You'll need to bind the Text property of each TextBox to
CurrentCustomer and then select the appropriate property from CurrentCustomer (FirstName,
LastName, etc.) in the data binding window.

14. Bind the Command property of each Button control to the appropriate command property
in the ViewModel (UpdateCustomerCommand or DeleteCustomerCommand) using the same
technique shown in the previous steps.
15. Drag a TextBlock control from the Toolbox and drop it directly to the right of the existing
Delete button. Change the Width of the TextBlock to 200.
16. Bind the newly added TextBlock control's Text property to the StatusMessage property of
the ViewModel using the data binding window.
17. Run the application and test the functionality. As you update or delete a Customer object a
success message should appear to the right of the Button controls. Select a different
customer and the success message should disappear.

Summary
In this exercise you converted the SilverlightCustomerViewer application to use the Model-View-
ViewModel pattern. Tasks completed include creating a service agent class for communication with a
WCF service as well as a ViewModel class that is responsible for retrieving data and storing it in
properties. You also added support for commanding and bound a ViewModel class to a XAML view.
Requirements satisfied in this lab include:
Remove code located in a Silverlight code-beside file
MVVM 18 | P a g e
Building Business Applications in Silverlight 4

Create a service agent interface and class to handle calls to a WCF service
Create a ViewModelBase class to handle INotifyPropertyChanged notifications
Create a ViewModel class that derives from ViewModelBase and handles data interactions
Add support for commanding into a ViewModel class
Bind a ViewModel class to a View in XAML
Bind Silverlight controls to ViewModel properties

MVVM 19 | P a g e

You might also like