Click here to Skip to main content
15,867,488 members
Articles / Programming Languages / C# 4.0

Expression Blendable Silverlight View Model Communication

Rate me:
Please Sign up or sign in to vote.
4.93/5 (10 votes)
26 Sep 2010Ms-PL3 min read 54.4K   505   13   13
Easily implement two-way communication between Master and Child View Models that works with Microsoft Expression Blend
Image 1

Easy 'Blendable' View Model Communication

Live example at this link.

In the article, Silverlight View Model Communication, we covered View Model Communication, but it was only one way.

Image 2

In the Silverlight Debate Forum project, the developers asked for two way communication, and they wanted it to be 'blendable', meaning, they could use Microsoft Expression Blend, to easily select ICommands and set properties in any View Model control, from any View Model control.  

Image 3

The end result, allows you to call any Master or Child control, from any Master or Child control.

How It Works

Image 4

The diagram above explains how this works. If you find it confusing, don't worry, we will try to cover this in a few different ways.

Image 5

The Child1ViewModel has an instance of MainPageViewModel in it's View Model. it is able to use this instance to call any ICommand, or read and set any Properties, in the Main Page View Model.

Image 6

Also, the Main Page View Model contains the View Model of the other Child View Models, so a Child View Model is able to communicate through the Main Page View Model, to call any ICommand, or read and set any Properties, in any of the other Child View Models!

The Code - The Child Control

The code for the Child View Model is as follows:

C#
public class Child1ViewModel : INotifyPropertyChanged
{
    public Child1ViewModel()
    {
        Child1RaiseCommand = new DelegateCommand(Child1Raise, CanChild1Raise);
    }
    
    public ICommand Child1RaiseCommand { get; set; }
    public void Child1Raise(object param)
    {
        Message = (String)param;
    }
    
    private bool CanChild1Raise(object param)
    {
        return true;
    }
    
    private string _Message;
    public string Message
    {
        get { return _Message; }
        set
        {
            if (Message == value)
            {
                return;
            }
            _Message = value;
            this.NotifyPropertyChanged("Message");
        }
    }
    
    private MainPageViewModel _objMainPageViewModel;
    public MainPageViewModel objMainPageViewModel
    {
        get { return _objMainPageViewModel; }
        set
        {
            if (objMainPageViewModel == value)
            {
                return;
            }
            _objMainPageViewModel = value;
            this.NotifyPropertyChanged("objMainPageViewModel");
        }
    }
    
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    #endregion
}

Notice that it contains:

  • A Message Property to display the message set by the Child1RaiseCommand ICommand
  • A Property to hold an instance of MainPageViewModel (objMainPageViewModel)
Image 7

The blue box surrounding the objMainPageViewModel property shows how it allows us to navigate through that property to call an ICommand on the Main Page View Model, or another Child View Model.

Image 8

However, it is important that only the DataContext for the XAML page is set to point to the View Model for the Child control. If you set the Data Context for any other element in the XAML of the control, the communication will not work.

The Code - The Main Control

The code for the Main Page View Model is as follows:

C#
public class MainPageViewModel : INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        RaiseCommand = new DelegateCommand(Raise, CanRaise);
        
        // Create instances of each ViewModel for each Child Control
        // Set an instance of the MainPage View Model in each 
        // View Model for each Child Control
        // The Child Controls onb the View of The Main Page will
        // be bound to these properties
        objChild1ViewModel = new Child1ViewModel();
        objChild1ViewModel.objMainPageViewModel = this;
        
        objChild2ViewModel = new Child2ViewModel();
        objChild2ViewModel.objMainPageViewModel = this;
    }
    
    #region RaiseCommand
    public ICommand RaiseCommand { get; set; }
    public void Raise(object param)
    {
        Message = (String)param;
    }
    
    private bool CanRaise(object param)
    {
        return true;
    }
    #endregion
    
    private string _Message;
    public string Message
    {
        get { return _Message; }
        private set
        {
            if (Message == value)
            {
                return;
            }
            _Message = value;
            this.NotifyPropertyChanged("Message");
        }
    }
    
    private Child1ViewModel _objChild1ViewModel;
    public Child1ViewModel objChild1ViewModel
    {
        get { return _objChild1ViewModel; }
        set
        {
            if (objChild1ViewModel == value)
            {
                return;
            }
            _objChild1ViewModel = value;
            this.NotifyPropertyChanged("objChild1ViewModel");
        }
    }
    
    private Child2ViewModel _objChild2ViewModel;
    public Child2ViewModel objChild2ViewModel
    {
        get { return _objChild2ViewModel; }
        set
        {
            if (objChild2ViewModel == value)
            {
                return;
            }
            _objChild2ViewModel = value;
            this.NotifyPropertyChanged("objChild2ViewModel");
        }
    }
    
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    #endregion
}

Notice that it contains:

  • A Property to hold an instance of each Child View Model (objChild1ViewModel and objChild2ViewModel)
  • It sets an instance of itself when it initializes each Child View Model Property, in its constructor (objChild1ViewModel.objMainPageViewModel = this)

Image 9

The diagram above shows how we are now able to call ICommands in the Child View Models.

Image 10

The thing that ties it all together, is that in Microsoft Expression Blend, we place a Child Control on the Main Page...

Image 11

In the Properties for the control, we select Advanced options.

Image 12

We select Data Binding...

Image 13

We bind the DataContext for the Child Control to the property in the Main Page View Model.

We also set it to TwoWay binding.

It Is Now Blendable

Image 14

In the designer in Expression Blend, if we click on a Button in the Child Control...

Image 15

In the Properties, we select Advanced options next to Command (under Miscellaneous).

Image 16

We can then navigate to any ICommand or Property in any View Model in the application.

Other Methods

There are other methods to achieve communication between View Models. There are various MVVM frameworks that provide Messaging. The advantage of these frameworks is that they are loosely-coupled. However, for the Silverlight Debate Forum project, if we require changes in the future, we will just make any needed changes to the code.

The primary advantage for that project is that since it uses MEF to dynamically load the Views, a Designer will be able to implement the View Model Communication without needing to touch any code. Everything the Designer needs will be available in Expression Blend.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft MVP. He is a ASP.NET and
C# programmer.
He is the founder of
AiHelpWebsite.com,
LightSwitchHelpWebsite.com, and
HoloLensHelpWebsite.com.

He has a son, Zachary and resides in Los Angeles with his wife Valerie.

He is the Author of:

Comments and Discussions

 
GeneralMy vote of 5 Pin
Jason Down12-Feb-13 13:59
Jason Down12-Feb-13 13:59 
GeneralRe: My vote of 5 Pin
defwebserver12-Feb-13 14:20
defwebserver12-Feb-13 14:20 
GeneralMy vote 10+ Pin
Member 165621424-May-11 8:39
Member 165621424-May-11 8:39 
GeneralRe: My vote 10+ Pin
defwebserver24-May-11 10:00
defwebserver24-May-11 10:00 
Generalnice Pin
giridhar 35-Oct-10 7:32
giridhar 35-Oct-10 7:32 
GeneralRe: nice Pin
defwebserver5-Oct-10 7:57
defwebserver5-Oct-10 7:57 
Thank You!
GeneralMy vote of 5 Pin
linuxjr30-Sep-10 1:38
professionallinuxjr30-Sep-10 1:38 
GeneralRe: My vote of 5 Pin
defwebserver1-Oct-10 17:53
defwebserver1-Oct-10 17:53 
GeneralRe: My vote of 5 Pin
jportelas18-Nov-10 5:49
jportelas18-Nov-10 5:49 
GeneralRe: My vote of 5 Pin
defwebserver18-Nov-10 6:14
defwebserver18-Nov-10 6:14 
GeneralRe: My vote of 5 Pin
jportelas18-Nov-10 9:16
jportelas18-Nov-10 9:16 
GeneralMy vote of 5 Pin
Marcelo Ricardo de Oliveira27-Sep-10 2:35
mvaMarcelo Ricardo de Oliveira27-Sep-10 2:35 
GeneralRe: My vote of 5 Pin
defwebserver27-Sep-10 2:52
defwebserver27-Sep-10 2:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.