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";
}
}
Public Class MainViewModel
Inherits ViewModelBase
Dim _DetailViewModel As DetailViewModel
Public ReadOnly Property DetailViewModel As DetailViewModel
Get
Return _DetailViewModel
End Get
End Property
Public Sub New()
_DetailViewModel = New DetailViewModel()
DirectCast(_DetailViewModel, ISupportParameter).Parameter = "Document 1"
End Sub
End Class
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 {
//...
}
}
}
Public Class DetailViewModel
Inherits ViewModelBase
Protected Overrides Sub OnParameterChanged(parameter As Object)
MyBase.OnParameterChanged(parameter)
If IsInDesignMode Then
'...
Else
'...
End If
End Sub
End Class
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.
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
View 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>
namespace Example.ViewModel {
public class MainViewModel {
public virtual string Parameter1 { get; set; }
public virtual string Parameter2 { get; set; }
public void ChangeParameter1() {
counter1++;
Parameter1 = "Parameter #" + counter1.ToString();
}
public void ChangeParameter2() {
counter2++;
Parameter2 = "Parameter #" + counter2.ToString();
}
int counter1 = 0;
int counter2 = 0;
}
}
using DevExpress.Mvvm;
namespace Example.ViewModel {
public class ChildViewModelBase : ViewModelBase {
IMessageBoxService MessageBoxService { get { return GetService<IMessageBoxService>(ServiceSearchMode.PreferParents); } }
protected override void OnParameterChanged(object parameter) {
base.OnParameterChanged(parameter);
if(parameter is string)
MessageBoxService.Show("ChildViewModelBase: Parameter = " + (string)parameter);
}
}
}
<UserControl x:Class="Example.View.ChildView1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:Example.ViewModel"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<ViewModel:ChildViewModelBase/>
</UserControl.DataContext>
<Grid>
<TextBlock Text="This View has a ViewModel derived from the ViewModelBase class" TextWrapping="Wrap"/>
</Grid>
</UserControl>
<UserControl x:Class="Example.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:Example.ViewModel"
xmlns:View="clr-namespace:Example.View"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="600"
DataContext="{dxmvvm:ViewModelSource ViewModel:MainViewModel}">
<dxmvvm:Interaction.Behaviors>
<dx:DXMessageBoxService/>
</dxmvvm:Interaction.Behaviors>
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button Content="Change Parameter1" Command="{Binding ChangeParameter1Command}"/>
<Button Content="Change Parameter2" Command="{Binding ChangeParameter2Command}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Border BorderThickness="1" BorderBrush="Black" Margin="10" Width="300" Height="100">
<View:ChildView1 dxmvvm:ViewModelExtensions.ParentViewModel="{Binding DataContext, ElementName=LayoutRoot}"
dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext.Parameter1, ElementName=LayoutRoot}"/>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Border BorderThickness="1" BorderBrush="Black" Margin="10" Width="300" Height="100">
<View:ChildView2 dxmvvm:ViewModelExtensions.ParentViewModel="{Binding DataContext, ElementName=LayoutRoot}"
dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext.Parameter2, ElementName=LayoutRoot}"/>
</Border>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
<UserControl x:Class="Example.View.ChildView2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:Example.ViewModel"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{dxmvvm:ViewModelSource ViewModel:ChildPOCOViewModel}">
<Grid>
<TextBlock Text="This View has a POCO ViewModel" TextWrapping="Wrap"/>
</Grid>
</UserControl>
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
namespace Example.ViewModel {
public class ChildPOCOViewModel : ISupportParameter {
[ServiceProperty(SearchMode=ServiceSearchMode.PreferParents)]
protected virtual IMessageBoxService MessageBoxService { get { return null; } }
public virtual object Parameter { get; set; }
protected virtual void OnParameterChanged() {
if(Parameter is string)
MessageBoxService.Show("ChildPOCOViewModel: Parameter = " + (string)Parameter);
}
}
}