我有一个MVVM应用程序,需要在屏幕之间进行基本的后退/前进导航。目前,我使用一个 WorkspaceHostViewModel 实现了这一点,该视图模型跟踪当前的工作区,并按如下方式公开必要的导航命令。
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; }
}
我还有一个WorkspaceHostView,它绑定到WorkspaceHostViewModel如下。
<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>
在WorkspaceHostResources.xaml文件中,我使用DataTemplates来关联WPF应该使用的视图来渲染每个WorkspaceViewModel。<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>
这个方案运作得相当好,但是存在一个缺点,由于 DataTemplates 的机制,在每次导航之间 Views 都会被重新创建。如果视图包含复杂的控件,比如 DataGrids 或 TreeViews,它们的内部状态就会丢失。例如,如果我有一个带有可展开和可排序行的 DataGrid,则当用户导航到下一个屏幕,然后返回到 DataGrid 屏幕时,展开/折叠状态和排序顺序会丢失。在大多数情况下,可以跟踪需要在导航之间保留的每个状态信息,但这似乎是一种非常不优雅的方法。是否有更好的方法来保留视图的整个状态,以便在更改整个屏幕的导航事件之间进行保留?
Loaded
确实会触发。这让我担心它可能会泄漏内存(更不用说那个事件会很方便)。你有注意到吗?有什么想法为什么会这样? - DonBoitnottdataGrid.ScrollIntoView(log)
?目前布局已缓存,但UI更改的代码后处理程序无法工作。 - Ankush Madankar