Silverlight continues to grow in popularity as companies realize the different ways it can be used to build both consumer and enterprise applications. If you're looking to get started with Silverlight or simply want to enhance your existing skills we've planned some great sessions at Silverlight Connections Las Vegas (November 1-4, 2010). Whether you're starting from scratch or already experienced and looking to take your skills to the next level, there is definitely a session for you. Here's a list of some of the topics that will be covered:
- Getting Started with Silverlight Development
- Building Silverlight Applications for Windows Phone 7
- Securing Silverlight Applications
- Expression Blend Design Principles and Techniques
- Advanced WCF RIA Services
- Using Managed Extensibility Framework (MEF)
- Using the MVVM Pattern
- The Silverlight Navigation Framework
- Much more! You can view a complete list of sessions at DevConnections.com
One of the sessions I'll be giving focuses on the Model-View-ViewModel (MVVM) pattern which developers can use to build a solid architecture around Silverlight applications. Here's an introductory look at the MVVM pattern and how to get started using it (it’s a topic I posted on awhile back). In my session, I’ll cover additional topics such as commanding and messaging and provide some in-depth samples to highlight topics and techniques.
Getting Started with the MVVM Pattern
The MVVM pattern defines three key parts including the Model, the View and the ViewModel. The following image shows a slide from a Silverlight course run that sums up the role of each part of the MVVM pattern in a concise way:
Looking through the description of each part you can see that the Model represents the business domain which includes the model classes used (Customer, Order, etc.), data access code and business rules. In general you can think of the Model as representing the entities that live on the server as well as the objects that are responsible for interacting with the data store your application uses and filling entities with data. While some people feel that the Model represents only the model classes (classes like Customer, Order, etc.) used in the application I personally think of it more broadly and include data access code and business rules in the Model definition. Silverlight applications will call into the Model code through services written using WCF, ASMX, REST or even custom solutions.
The View in MVVM represents the Silverlight screens that you build. This includes the XAML files and the code-beside files that are responsible for showing data to end users. The View's responsibilities include displaying data and collecting data from end users. A given View isn't responsible for retrieving data, performing any business rules or validating data.
The ViewModel acts as the middle-man between the View and the Model. It's responsible for aggregating and storing data that will be bound to a View. For example, a ViewModel may contain a List<State> property and a List<Person> property that may be bound to two ComboBox controls in a View. The ViewModel will retrieve the values held by these two properties from the Model. By using a ViewModel the View doesn't have to worry about retrieving data and knows nothing about where data comes from.
Additional players may be added into the Model-View-ViewModel mix to help segregate code even further. For example, I normally create a service agent class that is responsible for making calls from Silverlight to remote services. The service agent is responsible for initiating the service call, capturing the data that's returned and forwarding the data back to the ViewModel. By doing this the ViewModel classes can delegate data gathering responsibilities to the service agent. A given service agent can also be re-used across multiple ViewModel classes as needed. The following image shows how the service agent can be integrated into the MVVM pattern:
When developers first start building Silverlight applications they typically add all of the code for the application into the XAML's code-beside file (MainPage.xaml.cs for example). Although this approach certainly works, by following the MVVM pattern you can take advantage of several inherent benefits including better code re-use, simplified maintenance, more modular code and enhanced testing support. I'll focus on the overall benefits achieved by building applications that are based on the MVVM pattern throughout the rest of this article.
The Model
There are many different ways that the Model can be created including using Microsoft's Entity Framework or LINQ to SQL technologies, nHibernate, PLINQO, SubSonic, custom solutions and more. The technology chosen is generally unique to a given company's development policies so I'm not going to go into a discussion of the pros and cons of each technology here. What's important is that one or more classes used by a Silverlight application are "modeled" using tools or by writing code by hand. This involves defining all of the properties that each class will expose. A simple example of a Model class is shown next:
public class Person { public string FirstName { get;set;} public string LastName { get;set; } public int Age { get; set; } }
Once the Model classes are in place they'll need to be populated with data from a data store which can be done by writing custom code or using ORM frameworks that handle mapping query results to object instances. Services will also need to be written to expose one or more of the Model classes used in a Silverlight application which can be done using WCF, ASMX or even custom REST services.
The View and ViewModel Classes
Once the Model is ready to go, you can create the View and ViewModel classes. As mentioned earlier, a View represents a Silverlight screen that end users interact with which includes the XAML file and the associated code-beside file. Rather than adding all of the code to call the Model and retrieve data directly into the View's code-beside file, the View will rely on a ViewModel class to retrieve data and then bind to the properties of the ViewModel.
ViewModel classes should implement an interface that's available in Silverlight called INotifyPropertyChanged which defines a single event named PropertyChanged. This event is used to notify different Silverlight bindings that data has changed for one or more properties so that controls can be updated automatically. Although INotifyPropertyChanged can be implemented directly on a ViewModel class, your application may have multiple ViewModel classes in it and writing the same code over and over tends to get old. Creating a base ViewModel class that handles implementing INotifyPropertyChanged is useful to minimize code and allow more re-use to occur in applications. The following code shows a class named ViewModelBase that implements the INotifyPropertyChanged interface. The class also provides an OnNotifyPropertyChanged method that can be used to raise the PropertyChanged event.
public class ViewModelBase : INotifyPropertyChanged { protected void OnNotifyPropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(p)); } } public bool IsDesignTime { get { return (Application.Current == null) || (Application.Current.GetType() == typeof(Application)); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion }
A ViewModel class can derive from ViewModelBase and automatically take advantage of the INotifyPropertyChanged interface. An example of a ViewModel class named PeopleViewModel that derives from the ViewModelBase class and defines several properties and methods is shown next:
public class PeopleViewModel : ViewModelBase { IServiceAgent _ServiceAgent; Person _Person; ObservableCollection<Person> _People; public PeopleViewModel() : this(new ServiceAgent()) {} public PeopleViewModel(IServiceAgent serviceAgent) { if (!IsDesignTime) { _ServiceAgent = serviceAgent; GetPeople(); } } #region Properties public Person Person { get { return _Person; } set { if (_Person != value) { _Person = value; OnNotifyPropertyChanged("Person"); } } } public ObservableCollection<Person> People { get { return _People; } set { if (_People != value) { _People = value; OnNotifyPropertyChanged("People"); } } }
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.