避免Prism AutoWireViewModel创建ViewModel两次

时间:2017-03-01 19:00:53

标签: wpf prism

如果视图上有一个arg构造函数,Prism可以创建一个不需要的ViewModel。我试图理解如何避免这种情况,或者,如果我可以设计一些不同的工作方式。这是发生的事情。

XAML视图声明了ViewModelLocator.AutoWireViewModel:

mvvm:ViewModelLocator.AutoWireViewModel="True"

该类声明了两个构造函数:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public MainWindow(MainWindowViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;
    }
}

有一个原因我声明了one-arg构造函数:这是因为ViewModel是可序列化的;并且在反序列化时,通过使用恢复的ViewModel显式调用该构造函数来构造视图。但问题可以通过两种方式发生。

首先,当你调用one-arg构造函数时:

MainWindowViewModel viewModel = new MainWindowViewModel();
MainWindow window = new MainWindow(viewModel);

然后Prism构造视图,并从XAML调用ViewModelLocator,它创建并设置ViewModel ......然后设置显式参数;替换自动创建的实例(或者如果你反转构造函数中的行,实际上擦除了显式参数)。

并且,或许意外地,或者可能是由于我的理解中的某些愚蠢或者其他一些未知的设计方面,如果您从Container解析视图也会发生 - 您可能会这样做,期望调用默认构造函数风景;但实际上并没有发生;并且,您将再次创建两个ViewModel:

MainWindow window = Container.Resolve<MainWindow>();

这行代码实际上首先是在View上发现one-arg构造函数,然后解析ViewModel并调用该构造函数......再次触发XAML auto-ViewModel;然后你的one-arg构造函数继续擦除auto-ViewModel ...

消耗资源;事实上,我绊倒了一个异常,其中视图绑定基于一些与我期望明确设置的ViewModel不一致的其他状态。

我无法看到打败自动创建的实例的方法,因此我没有看到如何围绕AutoWireViewModel行为调用one-arg构造函数;或者,如何从Container中解析视图并避免创建两个ViewModel。

如果没有注册,也许从容器中解析View是滥用,但是one-arg构造函数似乎是合理的,它会创建两个实例......

有什么办法吗? [也许您可以自定义该行为以检查现有的DataContext,然后如果存在则不设置它......或沿着这些行的某些内容?]

我在GitHub上创建了一个简单的例子:

https://github.com/steevcoco/PrismAutoCreatesViewModelTwice

2 个答案:

答案 0 :(得分:1)

要明确这一点,Prism并没有两次创建ViewModel。你是。您可以使用ctor在后面的代码中执行一次,然后使用ViewModelLocator再次执行此操作。选择一种方法并使用它。没有必要在同一个视图上设置两种不同的VM方式。

您应该阅读容器及其工作原理。这将有助于您了解这里发生的事情。每件事情都完全正常。

答案 1 :(得分:0)

嗯,对于它的价值,我实际上实现了一个可以解决此问题的自定义ViewModelLocator。它有些粗糙:它只是首先检查当前的DataContext是否为非null;如果是这样,AutoWire将不会创建或设置Viewmodel。

我已经为感兴趣的人更新了存储库中的代码。