I have an MVVM application that requires basic backward/forward navigation between screens. Currently, I have implemented this using a WorkspaceHostViewModel that tracks the current workspace and exposes the necessary navigation commands as follows.
public class WorkspaceHostViewModel : ViewModelBase
{
private WorkspaceViewModel _currentWorkspace;
public WorkspaceViewModel CurrentWorkspace
{
get { return this._currentWorkspace; }
set
{
if (this._currentWorkspace == null
|| !this._currentWorkspace.Equals(value))
{
this._currentWorkspace = value;
this.OnPropertyChanged(() => this.CurrentWorkspace);
}
}
}
private LinkedList<WorkspaceViewModel> _navigationHistory;
public ICommand NavigateBackwardCommand { get; set; }
public ICommand NavigateForwardCommand { get; set; }
}
I also have a WorkspaceHostView that binds to the WorkspaceHostViewModel as follows.
<Window x:Class="MyNavigator.WorkspaceHostViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary Source="../../Resources/WorkspaceHostResources.xaml" />
</Window.Resources>
<Grid>
<!-- Current Workspace -->
<ContentControl Content="{Binding Path=CurrentWorkspace}"/>
</Grid>
</Window>
In the WorkspaceHostResources.xaml file, I associate the View that WPF should use to render each WorkspaceViewModel using DataTemplates.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNavigator">
<DataTemplate DataType="{x:Type local:WorkspaceViewModel1}">
<local:WorkspaceView1/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:WorkspaceViewModel2}">
<local:WorkspaceView2/>
</DataTemplate>
</ResourceDictionary>
This works pretty well, but one disadvantage is that the Views are recreated between each navigation due to the mechanics of DataTemplates. If the view contains complex controls, like DataGrids or TreeViews, their internal state is lost. For example if I have a DataGrid with expandable and sortable rows, the expand/collapse state and sort order is lost when the user navigates to the next screen and then back to the DataGrid screen. In most cases it would be possible to track each piece of state information that needs to be preserved between navigations, but it seems like a very inelegant approach.
Is there a better way to preserve the entire state of a view between navigation events that change the entire screen?