避免 Prism AutoWireViewModel 两次创建 ViewModel

Avoid Prism AutoWireViewModel Creating the ViewModel Twice

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

XAML 视图声明 ViewModelLocator.AutoWireViewModel:

mvvm:ViewModelLocator.AutoWireViewModel="True"

并且 class 声明了两个构造函数:

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

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

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

首先,当您调用单参数构造函数时:

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

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

并且,也许是出乎意料的,或者可能是我理解中的一些愚蠢行为,或者是其他一些未知的设计方面,如果您从容器中解析视图,它也会发生——您可能会期望调用默认设置视图的构造函数;但实际上并没有发生;并且,您将再次创建两个 ViewModel:

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

这行代码实际上是从发现 View 上的单参数构造函数开始的,然后解析 ViewModel 并调用该构造函数……这再次触发了 XAML auto-ViewModel;然后您的单参数构造函数继续擦除自动 ViewModel ...

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

我看不到击败自动创建实例的方法,因此我看不到如何围绕 AutoWireViewModel 行为调用单参数构造函数;或者,如何从容器解析视图并避免创建两个 ViewModel。

如果未注册,从容器解析视图可能是滥用,但单参数构造函数似乎是合理的,它创建了两个实例...

有什么办法吗? [也许您可以自定义该行为以检查现有的 DataContext,然后在存在时不设置它……或者类似的东西?]

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

https://github.com/steevcoco/PrismAutoCreatesViewModelTwice

好吧,尽管如此,我实际上已经实现了一个自定义 ViewModelLocator 来解决此问题。它有点粗糙:它只是首先检查当前 DataContext 是否为非空;如果是这样,AutoWire 将不会创建或设置 Viewmodel。

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

这里要明确一点,Prism 并没有创建 ViewModel 两次。你是。你在后面的代码中用 ctor 做一次,然后用 ViewModelLocator 再做一次。选择一种方法并使用它。无需使用两种不同的方式在同一个视图上设置 VM。

您应该仔细阅读容器及其工作原理。这将有助于您了解这里发生的事情。一切都在正常工作。