我有一个像WPF UI的Outlook,左侧是导航,顶部是工具栏,底部是状态栏,全部都在DockPanel.
应用程序的"主要"区域DataGrid是LastChild,因此填充剩余空间,它目前看起来像这样:
<Grid DockPanel.Dock="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<views:View1 Grid.Column="0" Grid.Row="0"/>
<views:View2 Grid.Column="0" Grid.Row="0"/>
<views:View3 Grid.Column="0" Grid.Row="0"/>
<views:View4 Grid.Column="0" Grid.Row="0"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
这些视图都是用户控件,它们具有自己的ViewModel,其Visibility属性绑定到ViewModel 中的属性,并由导航窗格选择控制.选择导航窗格项时,主ViewModel会向视图的ViewModel发送消息,并在收到消息后,视图的ViewModels会相应地设置其Visibility属性...
现在,这种方法很好但感觉不对,因为这些视图的所有ViewModel都是在app start上实例化的,而不是在选择相关的导航窗格时提出有关性能和内存使用情况的问题...
我的问题是,如果有在不诉诸PRISM/MEF或一些其它的插件选择了不同的导航窗格中载入每个视图和视图模型"按需",当相关的导航窗格中选择卸载这些意见和的ViewModels的一种方式架构...而且,更一般的是如何在主视图中构建具有多个视图/ ViewModel"嵌入"的应用程序?
这是我做的:
首先,在您的主ViewModel(为主窗口提供服务的ViewModel)上添加一个Content属性:
object _content;
public object Content
{
get { return _content; }
set
{
_content = value;
RaisePropertyChanged("Content");
}
}
Run Code Online (Sandbox Code Playgroud)
当用户从视图切换到视图时,将该Content属性设置为他们选择的视图的相应ViewModel.
然后,在主窗口中,您可以使用ContentControl显示当前的Content ViewModel:
<ContentControl Content="{Binding Content}" />
Run Code Online (Sandbox Code Playgroud)
...以及其上方的某个位置,为Content可能设置为的各种ViewModel定义一个DataTemplate :
<DataTemplate DataType="{x:Type vm:FooViewModel}">
<my:FooUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BarViewModel}">
<my:BarUserControl />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
所以现在ContentControl将负责初始化和显示每个UserControl,具体取决于哪个ViewModel当前处于"活动状态".