【问题标题】:What is the best way to create window from ViewModel? [closed]从 ViewModel 创建窗口的最佳方法是什么? [关闭]
【发布时间】:2021-08-30 06:59:37
【问题描述】:

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

【问题讨论】:

标签: c# wpf mvvm


【解决方案1】:

我想知道在 MVVM 模式中从 ViewModel 创建窗口的最佳和最简单的方法是什么

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

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

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

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

获取 ViewModel 委托,通常在其创建时。 这称为依赖注入。
一个典型的依赖注入的地方就是App。

一个示例将链接到您之前的主题WPF MVVM binding command to Datacontext inside Datagrid

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资源中设置它比较方便。 为此,让我们创建一个简单的容器类:

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

在主窗口中,我们设置从定位器获取 DataContext:

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

【讨论】:

  • 什么是 Copy() 和 CopyValuesFrom()?
  • 这些是一些可能的建议方法。我把它作为一些必要逻辑的演示。在这种情况下,我的意思是 Copy () - 创建一个克隆进行编辑。由于编辑原始实例不会提供撤消所做更改的机会。 CopyValuesFrom () - 从另一个实例复制值,即从已编辑的克隆复制到原始实例。编辑后点击保存时产生
猜你喜欢
  • 1970-01-01
  • 2014-01-22
  • 2018-06-07
  • 2012-01-28
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 2014-12-10
相关资源
最近更新 更多