Passing Data Between ViewModels (ISupportParameter)

  • 4 minutes to read

The ViewModelBase class implements the ISupportParameter interface. This interface provides the Parameter property, that you can use to pass initial data to View Models.

NOTE

The POCO mechanism does not generate the ISupportParameter interface implementation automatically, but you can implement this interface in your POCO View Model manually.

The following code demonstrates how to set the ISupportParameter.Parameter property in code-behind when a Detail View Model is created from the Main View Model.

public class MainViewModel : ViewModelBase {
    public DetailViewModel DetailViewModel { get; private set; }
    public MainViewModel() {
        DetailViewModel = new DetailViewModel();
        ((ISupportParameter)DetailViewModel).Parameter = "Document 1";
    }
}

When the Parameter property is set, the ViewModelBase.OnParameterChanged virtual method is invoked. You can override the ViewModelBase.OnParameterChanged virtual method to process passed data.

public class DetailViewModel : ViewModelBase {
    protected override void OnParameterChanged(object parameter) {
        base.OnParameterChanged(parameter);
        if(IsInDesignMode) {
            //...
        } else {
            //...
        }
    }
}

Passing Data Between Loosely Coupled Main and Detail View Model

You can implement passing data from a Main to a Detail View Model when these View Models are loosely coupled, i.e., when View Models do not know about each other. In this case, you should set the ViewModelExtensions.Parameter attached property in XAML. The diagram below illustrates how it works.

ISupportParameter-scheme

Here, the Main View contains an instance of a Detail View. The Views' DataContexts are the MainViewModel and DetailViewModel respectively. To pass data from the Main View/Main ViewModel to the Detail ViewModel, assign the data to the ViewModelExtensions.Parameter attached property on the Detail View instance.

<UserControl x:Class="Example.View.MainView" ...
    xmlns:ViewModel="clr-namespace:Example.ViewModel"
    xmlns:View="clr-namespace:Example.View"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm">
    <UserControl.DataContext>
        <ViewModel:MainViewModel/>
    </UserControl.DataContext>
    <Grid x:Name="LayoutRoot">
        ...
        <!-- It is necessary to use the ElementName binding mode, 
        because the DetailView's DataContext is a DetailViewModel object. 
        That is why the following regular binding cannot be used 
        in this case: dxmvvm:ViewModelExtensions.Parameter="{Binding}"
        Instead, use one of the following constructions:-->
        <View:DetailView dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext, ElementName=LayoutRoot}"/>
        <ContentControl>
            <ContentControl.ContentTemplate>
                <DataTemplate>
                    <View:DetailView dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext, Source={x:Reference LayoutRoot}}"/>
                </DataTemplate>
            </ContentControl.ContentTemplate>
        </ContentControl>
        ...
    </Grid>
</UserControl>

How it works. When the Parameter attached property is set on the Detail View, the ViewModelExtensions class identifies whether the View's DataContext is a ViewModelBase descendant. To be more precise, the ViewModelExtensions class identifies whether the DataContext is an object that implements the ISupportParameter interface. If so, the ViewModelExtensions class passes the new Parameter value to the Detail View's ViewModel: the new value is assigned to the ViewModel's ISupportParameter.Parameter private property.

When the Parameter private property is changed, the Detail ViewModel calls its OnParameterChanged protected method. You can manually override the OnParameterChanged protected method to access and use the new parameter value.

Example

<Window x:Class="Example.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:View="clr-namespace:Example.View"
        Title="MainWindow" Height="600" Width="800">
    <Grid>
        <View:MainView/>
    </Grid>
</Window>