从 ViewModel 创建 window 的最佳方法是什么?

What is the best way to create window from ViewModel?

正如我的标题所暗示的,我想知道在 MVVM 模式中从 ViewModel 创建 window 的最佳和最简单的方法是什么。

i want to know what is the best and simplest method to create window from ViewModel in MVVM pattern

“最好”、“最简单”是非常主观的概念。
对于某些人来说,一个简单的实现可能被某些人认为是困难的。

这个题目很大,要详细回答这样的问题,你得写一本厚厚的教科书。
因此,简而言之,一般概念和可能实现的示例。

从 ViewModel 的角度来看,它无法“知道”Window 是什么。所以问这个问题“VM 应该如何创建 Window?” - 这是不正确的。
问题应该这样问:“VM如何调用外部对话?”。
如何为 VM 实现此对话框(WPF Window、表单或控制台输入)并不重要。
实际上,对话是对方法的委托,return 是对话结果。
在最简单的情况下,对话框的结果只是一个布尔值(成功/失败)。
假设 OpenFileDialog.ShowDialog returns Nullable <bool>.
在更复杂的情况下,枚举是 returned。 MessageBox 示例。
你需要什么样的对话结果取决于你的任务条件。

假设这是一个元素编辑对话框,那么它在参数中接收到一个要编辑的元素,它可以 return bool: true - 编辑完成,其结果需要保存,false -编辑取消。

获取 ViewModel 委托,通常是在其创建时。 这称为依赖注入。
依赖注入的典型位置是 App.

一个例子会link到你之前的话题

using System;
using System.Collections.ObjectModel;

namespace MoldsApp
{
    public class MainWindowViewModel
    {
        //A collection-property of type ObservableCollection is best implemented as «ReadOnly».
        public ObservableCollection<Molds> AllMolds { get; }

        private readonly Func<Molds, bool> editDialog;

        // Constructor receiving dialog delegate
        public MainWindowViewModel(Func<Molds, bool> editDialog)
        {
            this.editDialog = editDialog;
        }

        private LamdaCommand _editCommand;
        public LamdaCommand EditCommand => _editCommand
            ?? (_editCommand = new LamdaCommand(EditExecute, EditCanExecute));

        private bool EditCanExecute(object parameter)
            => parameter is Molds;

        private void EditExecute(object parameter)
        {
            Molds molds = (Molds)parameter;

            // At this point, there should be element preprocessing code.
            // Let's say copying for the possibility of canceling the result of editing.
            Molds moldsCopy = molds.Copy();

            // Calling a dialog and getting its result
            var result = editDialog(moldsCopy);

            if (result)
            {
                // Saving the result.
                // And changing the item to match the edited copy.

                Save(moldsCopy);
                molds.CopyValuesFrom(moldsCopy);
            }
        }

        private void Save(Molds moldsCopy)
        {
            throw new NotImplementedException();
        }
    }
}

MainWindowViewModel实例会在App中实例化。 为了让 Window 把它放到它的 DataContext 中,在 App 资源中设置它很方便。 为此,让我们制作一个简单的容器-class:

    public class Locator
    {
        public MainWindowViewModel MainVM { get; set; }
    }
<Application ----------
             ----------
             StartupUri="MainWindow.xaml"
             Startup="OnStartup">
    <Application.Resources>
        <moldsapp:Locator x:Key="locator"/>
    </Application.Resources>
</Application>

现在,在 App Code Behind 中,我们初始化所有这些:

    public partial class App : Application
    {
        private void OnStartup(object sender, StartupEventArgs e)
        {
            Locator locator = (Locator) Resources["locator"];
            locator.MainVM = new MainWindowViewModel(MoldsEditHandler);
        }

        private static bool MoldsEditHandler(Molds molds)
        {
            AddEditWindow window = new AddEditWindow()
            {
                DataContext = new AddEditWindowViewModel(molds)
            };
            var result = window.ShowDialog();

            return result == true;
        }
    }

在 Main Window 中,我们设置从定位器获取 DataContext:

<Window ---------
        -------------
        DataContext="{Binding MainVM, Source={StaticResource locator}}">