我有两个 DataTemplates 根据当前的 ViewModel 进行切换。但是,每当我切换 ViewModel 时,它似乎都会调用相应的 View 构造函数并调用构造函数中的 InitializeComponent() 调用,这意味着每当我切换 DataTemplate 时,它都会生成一个绑定到相应 DataTemplate 的新视图。我不确定为什么会发生这种情况,但是有没有办法在切换 ViewModel 时防止创建新视图?
下面是位于我的 MainView 的 DataTemplates。
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:FirstPanelViewModel}">
<views:FirstPanelView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:SecondPanelViewModel}">
<views:SecondPanelView />
</DataTemplate>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
模板显示在 ContentControl 中。
<ContentControl Grid.Row="1" Content="{Binding CurrentViewModel}" />
Run Code Online (Sandbox Code Playgroud)
这是我的 SecondPanelView,它与我的 FirstPanelView 相同,非常简单。
public partial class FirstPanelView
{
public FirstPanelView()
{
InitializeComponent();
}
}
public partial class SecondPanelView
{
public SecondPanelView()
{
InitializeComponent();
}
}
Run Code Online (Sandbox Code Playgroud)
我的 Ioc 确保我只生成 SecondPanelView 的一个实例
container.Register<IFirstPanelViewModel, FirstPanelViewModel>(new PerContainerLifetime())
container.Register<ISecondPanelViewModel, SecondPanelViewModel>(new PerContainerLifetime());
Run Code Online (Sandbox Code Playgroud)
每个视图中的 DataContext 都受自定义标记扩展的限制。
DataContext="{Binding Source={common:Locate}, Path=FirstPanelViewModel}"
DataContext="{Binding Source={common:Locate}, Path=SecondPanelViewModel}"
Run Code Online (Sandbox Code Playgroud)
这只是调用相应 ViewModel 的 GetInstance。
public IFirstViewModel FirstViewModel
{
get { return _container.GetInstance<IFirstPanelViewModel>(); }
}
public ISecondViewModel SecondViewModel
{
get { return _container.GetInstance<ISecondPanelViewModel>(); }
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是一个老问题,但我也在为这个问题而苦苦挣扎。答案是将视图实例直接放置在资源中,并将它们绑定到数据模板中的内容控件。如果这样做,视图只会实例化一次。
<Window.Resources>
<views:FirstPanelView x:Key="FirstPanelViewKey"/>
<views:SecondPanelView x:Key="SecondPanelViewKey"/>
<DataTemplate x:Key="DT1">
<ContentControl Content="{StaticResource FirstPanelViewKey}" />
</DataTemplate>
<DataTemplate x:Key="DT2">
<ContentControl Content="{StaticResource SecondPanelViewKey}" />
</DataTemplate>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)