MVVM - 数据模板创建一个新视图

Mik*_*ike 4 c# wpf mvvm

我有两个 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)