在 Wpf Core 应用程序中使用 MvvmCross 的 OpenFileDialog

OpenFileDialog using MvvmCross in a Wpf Core application

我最近开始了一个小项目来更新我所获得的一点点 wpf 知识并尝试新的东西。我对 MvvmCross 很感兴趣,但我想暂时保持它的小。我的目标是一个简单的图像操纵器;图像到 ascii、重新着色等等...

我的设置: Mvx 核心库(.NET Standard 2.0)

Wpf 应用程序 (.NET Core 3.1)

墙我运行变成了: 尝试获取 OpenFileDialog(命名空间:Microsoft.Win32)来执行此操作:

public void OpenFile_Clicked()
    {
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
        Nullable<bool> result = dlg.ShowDialog();
        if(result) {
            // big cash prize
        }
    }

我指定了命名空间,因为我发现有几篇文章讨论了 OpenFileDialog 上缺少引用。在我的例子中,awnser 是 .NET Standard。那里根本不存在 OpenFileDialog,这正是我的问题。当核心库必须是 .NET Standard 类型时,我应该如何在我的 ViewModel 中调用 OpenFileDialog?对 wpf 项目的依赖不会破坏整个 mvvm 模式吗?! 老实说:我已经阅读了整个 mvx 文档并找到了一些线索,但我的 wpf/mvvm/xaml 理解可能延伸到其中的三分之一。 MvvmCross Inversion of Control 文档看起来对我很有用,但我仍然不明白这在我的案例中是如何工作的。给定的示例 https://www.mvvmcross.com/documentation/fundamentals/inversion-of-control-ioc?scroll=43 没有显示这些接口的位置,对我来说,这一切都归结为我需要以某种方式将 OpenFileDialog 从 wpf 项目中移出到核心项目中。

"@BionicCode excuse my french but what are you talking about? "The click handler should be in the code-behind of the view"? I think you had a little switcheroo there. My MainViewModel has the method and command while my MainView binds to it. I think I did everything exactly right. edit: I also clarified that i did NOT intend to make my core dependant on the wpf project."

没问题。我想因为你是法国人,所以你完全误解了我。

我又来了:看来你用的是MVVM模式

要正确实现 MVVM,您必须遵循一些规则(模式)。
一条规则是不要将视图组件的职责与视图模型组件的职责混在一起。 根据定义,视图组件仅向用户显示数据并处理用户输入,例如收集数据或与用户交互。

用户输入始终是用户界面的一部分 (UI)。对话框是旨在与用户交互的控件(应用程序界面)。在您的情况下,对话框收集用户输入(文件路径)。
这就是为什么这个逻辑属于视图 => 而不是在 MainViewModel 中使用 OpenFile_Clicked 只是为了向用户显示 OpenFileDialogOpenFile_Clicked 应该是UI 的 code-behind 例如,MainWindow.xaml.cs.

此事件处理程序显示对话框并将结果(选择的文件路径)传递给 MainViewModel(使用数据绑定、命令模式或通过直接引用)。

"Wouldn't a dependency on the wpf project ruin the entire mvvm pattern?!"

不,不是对 WPF 项目的引用会破坏 MVVM 模式,而是对 OpenFileDialog class.
的引用 如果您遵循前面解释的原则并从您的 MainViewModel 中删除对 OpenFileDialog 的依赖,您将取回 MVVM 的优势。
换句话说:根本不要在 MainViewModel 中使用 OpenFileDialog 或任何其他视图组件。

"How am I supposed to call OpenFileDialog in my ViewModel when the Core library has to be of type .NET Standard?"

再说一次:根本不要在 MainViewModel 中使用 OpenFileDialog 或任何其他视图组件:

MainWindow.xaml.cs(WPF .NET Core 程序集)

partial class MainWindow
{
  // Event handler for Button.Click
  private void OnOpenDialogButton_Click(object sender, EventArgs e)
  {
    var dialog = new System.Windows.Forms.OpenFileDialog();
    dialog.Show();
    string selectedFilePath = dialog.FileName;

    this.ViewModel.HandleSelectedFile(selectedFilePath);
  }
}

MainViewModel.cs(.NET 标准库程序集)

public void HandleSelectedFile(string filePath)
{
  // TODO::Handle file e.g. open and read
}

使用 OpenFileDialog 强制引用程序集放弃 .NET 标准合规性。因为 OpenFileDialogSystem.Windows.Forms 中定义的 class,引用程序集需要使用 .NET Framework 或 .NET Core 库。
按照上面的示例将从 MainViewModel 中删除此依赖项并使您的库再次符合 .NET 标准。


"The MvvmCross Inversion of Control documentation looked useful to me but I still don't get how this would work in my case."

控制反转解决了一个不同的问题,与 MVVM 或显示视图模型中的对话框无关(不要这样做)。它使应用程序可以通过交换部件进行扩展。

由于您使用的是 .NET Core,因此您可以使用 IoC 容器中的构建:Overview of dependency injection