【问题标题】:OpenFileDialog using MvvmCross in a Wpf Core application在 Wpf Core 应用程序中使用 MvvmCross 的 OpenFileDialog
【发布时间】:2021-01-14 00:06:27
【问题描述】:

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

我的设置: Mvx Core Library (.NET Standard 2.0)

  • MainViewModel - 有方法 OpenFileDialog_Clicked 被输入到 openFileDialogCommand

Wpf 应用程序 (.NET Core 3.1)

  • MainView - 有一个带有按钮的菜单,该按钮绑定到 MainViewModel 上的 openFileDialogCommand

我撞到的墙: 尝试获取 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 缺少引用的文章。就我而言,遮阳篷是.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 项目中获取到核心项目中。

【问题讨论】:

  • 您应该使用库 Windows.Form。所有的Dialogs都是一个window dll comdlg32.dll (Common Dialog)。网络库(和 Excel VBA 等其他应用程序)创建包装器并使用不同的参数调用 dll(参见:pinvoke.net/default.aspx/comdlg32.GetOpenFileName)。
  • @jdweng 如果我理解正确,添加: [DllImport("Comdlg32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool GetOpenFileName(ref OpenFileName ofn);到我的 MainViewModel 应该完成工作吗?伟大的!我会在工作完成后回复最后一次。
  • 您不需要使用 DllImport。不知道为什么它丢失了。但是 Comdlg 会起作用。
  • "MainViewModel - 有方法 OpenFileDialog_Clicked" 为什么?这不是 MVVM。点击处理程序应该在视图的代码隐藏中。用户输入通常不应由视图模型处理。用户输入是视图组件 (UI) 的职责。
  • 删除此依赖项允许您将库限制为 .NET Standard 兼容性。否则,您将强制它与 .NET Framework 或 .NET Core 兼容,以便使用 System.Windows.Forms.dll 程序集。

标签: c# wpf .net-core mvvmcross openfiledialog


【解决方案1】:

“@BionicCode 请原谅我的法语,但你在说什么?” 单击处理程序应该在视图的代码隐藏中?我想你 那里有一个小切换器。我的 MainViewModel 有方法和 命令,而我的 MainView 绑定到它。我想我做了一切 非常正确。编辑:我还澄清说我不打算让我的 核心依赖于 wpf 项目。”

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

我将重新开始:看起来您正在使用 MVVM 模式。

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

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

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

“对 wpf 项目的依赖不会毁掉整个 mvvm 模式?!”

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

“我应该如何在我的 ViewModel 中调用 OpenFileDialog 核心库必须是 .NET Standard 类型?”

再次重申:不要使用OpenFileDialogMainViewModel 中的任何其他视图组件:

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 中定义的类,所以引用程序集需要使用.NET Framework 或.NET Core 库。
按照上面的示例将从MainViewModel 中删除此依赖项,并使您的库再次符合.NET Standard。


“MvvmCross 控制反转文档对我来说看起来很有用 但我仍然不明白这在我的情况下是如何工作的。”

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

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

【讨论】:

  • 你是对的,我完全误解了你。即使我不是法国人。我非常专注于将所有内容都保留在我的核心中,以至于我什至没有想到其他任何事情。我今天差不多完成了,不知道我是否会在明天之前打开我的项目,但我会尽快提供反馈!另外,请原谅我在那里生气。我没有理由这么急躁。
  • 工作起来几乎就像一个魅力。我遇到了 3 个问题,我想问你其中一个问题。 1. MvxWindow 不显示任何内容,因此我将处理程序移到了我的 MainView(工作得很好,因为它也位于 wpf 项目中)。 2. 我尝试使用 mvx:Bi.nd 而不是标准的“Click” -> 由于某种原因无法正常工作,所以我回到了“Click”。 3. 这个:link。这对我来说看起来很难看,所以我只使用了 Microsoft.Win32.OpenFileDialog 。有问题吗?!
  • 我才意识到 [2.] 是多么愚蠢。 mvx:Bi.nd 的全部目的是解决 viewmodel ...
  • Microsoft.Win32.OpenFileDialog 是在 WPF 应用程序上下文中使用的推荐对话框。它不需要引用 WindowsForms 程序集。 [1] 我理解你的应用程序结构的方式,点击处理程序应该在MainView。 [2] 没有数据绑定的场景。处理事件的单击处理程序非常完美。
猜你喜欢
  • 2014-03-31
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 2013-07-20
  • 1970-01-01
  • 2018-06-08
相关资源
最近更新 更多