Why MVVM Emerged as the Default Silverlight Pattern
Silverlight's data binding engine, combined with XAML's ability to declare bindings, resources, and control templates without any procedural code, makes it natural to push nearly all application logic out of code-behind and into a separate class that the view binds to, rather than having the view manipulate UI elements directly the way WinForms code-behind traditionally did. The Model-View-ViewModel pattern formalizes this: the Model represents domain data and business rules, the ViewModel exposes that data as bindable properties and commands with no reference to any UI control type, and the View is pure XAML that binds to the ViewModel's DataContext, meaning the same ViewModel logic can be unit tested without ever loading the Silverlight runtime or a visual tree.
Cricket analogy: It's like separating the team's tactical analyst from the players on the field; the analyst (ViewModel) works out strategy from match data (Model) independently of whoever happens to be fielding (View), so the strategy can be reviewed in a meeting room without a ball ever being bowled.
ViewModels, ICommand, and RelayCommand
Because XAML buttons bind their Command property to an object implementing ICommand rather than wiring a Click event in code-behind, a ViewModel typically exposes commands as properties of type ICommand, most commonly implemented with a RelayCommand (also called DelegateCommand) helper class that wraps an Action for Execute and a Func<bool> for CanExecute, letting the ViewModel say 'this Save operation is available' by re-evaluating CanExecute and raising CanExecuteChanged whenever relevant state changes, which Silverlight uses to automatically enable or disable the bound button without any code-behind reaching into the button's IsEnabled property directly.
Cricket analogy: It's like the third umpire's review button being physically wired to only activate when a review is actually available, rather than the on-field umpire manually checking eligibility and flipping a switch by hand each time.
INotifyPropertyChanged and Two-Way Binding
For a bound TextBox's edits to flow back into the ViewModel and for ViewModel changes to update the UI, both sides depend on INotifyPropertyChanged: the ViewModel implements it, and every settable property's setter raises PropertyChanged with the property's name so Silverlight's binding engine knows to re-read the value and refresh whatever controls are bound to it. A binding declared as {Binding Name, Mode=TwoWay} pushes user edits from the control back into the ViewModel property setter as the user types or on LostFocus depending on the property's UpdateSourceTrigger, while validation attributes or IDataErrorInfo implementations on the same property surface red validation borders directly in the bound control without any manual UI manipulation.
Cricket analogy: It's like the stadium's giant screen and the official scorebook staying perfectly in sync; whenever the scorer updates a run in the book, the screen refreshes automatically, and any correction on the screen's touch console updates the book too.
Locating ViewModels: DataContext Wiring and the MVVM Locator
The simplest way to connect a View to its ViewModel is setting DataContext in the View's constructor, but larger applications often use a ViewModelLocator, a single class registered as a static resource in App.xaml that exposes a property per screen, such as MainViewModel, so XAML can bind DataContext declaratively with {Binding Main, Source={StaticResource Locator}} instead of scattering DataContext assignments across code-behind files. Frameworks like MVVM Light and Prism formalize this further with a dependency injection container behind the locator, letting the same ViewModel type receive a real service implementation at runtime and a mock implementation during design-time or unit testing, without either the View or the ViewModel needing to know which one it got.
Cricket analogy: It's like a central team-selection committee assigning captains to squads through a single official process, rather than each squad manager privately deciding on their own captain, ensuring consistency and letting a reserve captain be swapped in for practice matches without changing the process.
public class MainViewModel : INotifyPropertyChanged
{
private string _customerName;
private bool _isSaving;
public string CustomerName
{
get { return _customerName; }
set
{
if (_customerName == value) return;
_customerName = value;
RaisePropertyChanged("CustomerName");
SaveCommand.RaiseCanExecuteChanged();
}
}
public RelayCommand SaveCommand { get; private set; }
public MainViewModel()
{
SaveCommand = new RelayCommand(ExecuteSave, CanExecuteSave);
}
private bool CanExecuteSave()
{
return !_isSaving && !string.IsNullOrWhiteSpace(CustomerName);
}
private void ExecuteSave()
{
_isSaving = true;
SaveCommand.RaiseCanExecuteChanged();
// call service, then on completion:
_isSaving = false;
SaveCommand.RaiseCanExecuteChanged();
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}Forgetting to raise PropertyChanged for a computed property that depends on another bound property is a classic MVVM bug: for example, if FullName is derived from FirstName and LastName, the FirstName setter must also raise PropertyChanged("FullName"), or the UI will silently show a stale value even though the underlying data changed correctly.
- MVVM splits an app into Model (domain data), View (pure XAML), and ViewModel (bindable state and commands with no UI references).
- Buttons bind Command to ICommand implementations like RelayCommand, which wrap Execute/CanExecute logic and raise CanExecuteChanged.
- INotifyPropertyChanged is required for two-way bindings to push ViewModel updates into the UI and vice versa.
- TwoWay bindings push user edits back into ViewModel setters, respecting UpdateSourceTrigger timing.
- A ViewModelLocator centralizes DataContext wiring and enables swapping real services for mocks in design-time or tests.
- ViewModels with no UI references can be unit tested without loading the Silverlight runtime or a visual tree.
- Forgetting to raise PropertyChanged for dependent computed properties is a common source of stale-UI bugs.
Practice what you learned
1. In MVVM, which component should have no reference to any UI control type?
2. What interface does a XAML Button's Command property typically bind to?
3. What must a ViewModel implement for two-way bindings to reflect property changes back to the UI?
4. What is the purpose of a ViewModelLocator?
5. A ViewModel has a FullName property computed from FirstName and LastName, but the UI shows a stale FullName after FirstName changes. What is the likely cause?
Was this page helpful?
You May Also Like
Silverlight and RIA Services
How WCF RIA Services generates a shared client/server data layer for Silverlight, cutting out the boilerplate of hand-writing DTOs, proxies, and validation twice.
Consuming WCF Services in Silverlight
How Silverlight applications call WCF services through generated asynchronous proxies, and the sandbox and binding constraints that shape every call.
Silverlight Networking
The networking stack Silverlight exposes for HTTP and socket communication, and the security boundaries that govern which requests are allowed to leave the plug-in.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics
Microsoft TechnologiesMVVM Design Pattern Study Notes
.NET · 30 topics