【问题标题】:MVVM - datatemplate creates a new viewMVVM - 数据模板创建一个新视图
【发布时间】:2016-11-22 22:53:36
【问题描述】:

我有两个根据当前 ViewModel 切换的 DataTemplate。但是,每当我切换 ViewModel 时,它似乎会调用相应视图的构造函数并调用构造函数中的 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>

模板正在 ContentControl 中显示。

<ContentControl Grid.Row="1" Content="{Binding CurrentViewModel}" />    

这是我的SecondPanelView,和我的FirstPanelView一样,很简单。

public partial class FirstPanelView
{
    public FirstPanelView()
    {
        InitializeComponent();
    }
}
public partial class SecondPanelView
{
    public SecondPanelView()
    {
        InitializeComponent();
    }
}

我的 Ioc 确保我只生成一个 SecondPanelView 实例

container.Register<IFirstPanelViewModel, FirstPanelViewModel>(new PerContainerLifetime())
container.Register<ISecondPanelViewModel, SecondPanelViewModel>(new PerContainerLifetime());

DataContext 在每个视图中都由自定义标记扩展限定。

DataContext="{Binding Source={common:Locate}, Path=FirstPanelViewModel}"
DataContext="{Binding Source={common:Locate}, Path=SecondPanelViewModel}"

这只是调用相应 ViewModel 的 GetInstance。

public IFirstViewModel FirstViewModel
{
    get { return _container.GetInstance<IFirstPanelViewModel>(); }
}
public ISecondViewModel SecondViewModel
{
    get { return _container.GetInstance<ISecondPanelViewModel>(); }
}

【问题讨论】:

  • 这是 WPF 设计的。如果视图超出范围,则视图将被销毁,如果需要再次显示,则必须重新创建。如果您使用 ViewModel 第一种方法,也就是 DataTemplates,就会发生这种情况。使用带有绑定源项和数据模板的 TabControl 也会发生同样的事情。即使 ViewModel 没有重新创建,视图也是如此。解决这个问题的唯一方法是让控制视图的创建方式。这可以在自定义控件中完成。见here
  • 您可以尝试this,但改为扩展 ContentControl。
  • 感谢您的建议。我会试试这个方法。
  • 您的问题似乎涉及基本 WPF API 之外的一些基础设施。 container 是什么?您具体使用的是什么 API?在 WPF 中,您的问题的答案很简单,您需要确保两个视图都保持实例化,即保留两个视图模型对象,并隐藏/显示适当的对象(例如,将每个视图模型的标志绑定到视图的可见性,表示哪个是活动的)。但是您使用的任何其他 API 都可以更优雅地完成此操作。
  • 当然,还有“你为什么关心?”的问题。 IE。按需重新创建视图真的有那么糟糕吗?

标签: c# wpf mvvm


【解决方案1】:

即使在扩展 ContentControl 之后,我也无法解决我的问题。我在使用该方法时遇到的问题是 ContentControl 的依赖属性不能直接交互/覆盖,这迫使我破解现有的依赖属性。此外,DataTemplate 的初始化似乎比简单的 ContentControl 更深。

因此,我决定通过简单地切换视图的可见性来更改视图的显示方式。这种方法对我有用,因为我本质上希望我的视图留在后台做自己的事情,并随时准备以之前的状态进行交互。

【讨论】:

    【解决方案2】:

    这是一个老问题,但我也在努力解决这个问题。答案是将视图实例直接放在资源中,并将它们绑定到数据模板中的内容控件。如果这样做,视图只会被实例化一次。

    <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>
    

    【讨论】:

    • 如果你有一个 List 并且你想为每个项目提供不同的视图怎么办?所以 UI 只会显示活动的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    相关资源
    最近更新 更多