如何通过MVVM在WPF应用程序中使用FolderBrowserDialog [英] How to use a FolderBrowserDialog from a WPF application with MVVM

查看:52
本文介绍了如何通过MVVM在WPF应用程序中使用FolderBrowserDialog的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 <代码我的WPF应用程序中的> FolderBrowserDialog -没什么.我不太在乎它具有Windows窗体外观.

I'm trying to use the FolderBrowserDialog from my WPF application - nothing fancy. I don't much care that it has the Windows Forms look to it.

我找到了一个具有适当答案的问题(如何使用WPF应用程序中的FolderBrowserDialog ),但我使用的是MVVM.

I found a question with a suitable answer (How to use a FolderBrowserDialog from a WPF application), except I'm using MVVM.

是我实施"的答案,但无法获得窗口对象,而我只是不带任何参数调用 ShowDialog().

问题是这样的:

var dlg = new FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dlg.ShowDialog(this.GetIWin32Window());

在我的 ViewModel 中, this 没有用于我获取Window上下文的 GetIWin32Window()方法.

In my ViewModel there the this has no GetIWin32Window() method for me to get the Window context.

关于如何进行这项工作的任何想法?

Any ideas on how to make this work?

推荐答案

首先,您可以使用不需要窗口的ShowDialog签名.

First, you could use the ShowDialog signature that does not require a window.

var dlg = new FolderBrowserDialog();
DialogResult result = dlg.ShowDialog();

第二,您可以将应用程序的主窗口作为拥有窗口发送.

Second, you could send the main window of the Application as the owning window.

var dlg = new FolderBrowserDialog();
DialogResult result = dlg.ShowDialog(Application.Current.MainWindow.GetIWin32Window());

第二个选项可能不被视为非常MVVMish.

The second option might not be considered very MVVMish.

通过@ 博士查看答案.此问题中的ABT ,用于注入将您的View指向ViewModel的指针(不确定这是一个好主意还是一个坏主意,但我不会阻止我停止前进)使用这种技术,如果您可以在VM中访问相应的View我真的想让View成为FolderBrowserDialog的所有者.

See the answer by @Dr. ABT in this question for a way to inject a pointer to your View into your ViewModel (not sure if this is a good idea or a bad idea, but I'm not going to let that stop me) With this technique, you would have access in your VM to the corresponding View if you really want to make that View be the owner of the FolderBrowserDialog.

@ChrisDD关于定义接口和包装FolderBrowserDialog是正确的.我们就是这样做的:

@ChrisDD is right about defining an interface and wrapping FolderBrowserDialog. That is how we do it:

  public interface IFolderBrowserDialog
  {
    string Description { get; set; }
    Environment.SpecialFolder RootFolder { get; set; }
    string SelectedPath { get; set; }
    bool ShowNewFolderButton { get; set; }
    bool? ShowDialog();
    bool? ShowDialog(Window owner);
  }

  //Decorated for MEF injection
  [Export(typeof(IFolderBrowserDialog))]
  [PartCreationPolicy(CreationPolicy.NonShared)]
  internal class WindowsFormsFolderBrowserDialog : IFolderBrowserDialog
  {
    private string _description;
    private string _selectedPath;

    [ImportingConstructor]
    public WindowsFormsFolderBrowserDialog()
    {
      RootFolder = System.Environment.SpecialFolder.MyComputer;
      ShowNewFolderButton = false;
    }

    #region IFolderBrowserDialog Members

    public string Description
    {
      get { return _description ?? string.Empty; }
      set { _description = value; }
    }

    public System.Environment.SpecialFolder RootFolder { get; set; }

    public string SelectedPath
    {
      get { return _selectedPath ?? string.Empty; }
      set { _selectedPath = value; }
    }

    public bool ShowNewFolderButton { get; set; }

    public bool? ShowDialog()
    {
      using (var dialog = CreateDialog())
      {
        var result = dialog.ShowDialog() == DialogResult.OK;
        if (result) SelectedPath = dialog.SelectedPath;
        return result;
      }
    }

    public bool? ShowDialog(Window owner)
    {
      using (var dialog = CreateDialog())
      {
        var result = dialog.ShowDialog(owner.AsWin32Window()) == DialogResult.OK;
        if (result) SelectedPath = dialog.SelectedPath;
        return result;
      }
    }
    #endregion

    private FolderBrowserDialog CreateDialog()
    {
      var dialog = new FolderBrowserDialog();
      dialog.Description = Description;
      dialog.RootFolder = RootFolder;
      dialog.SelectedPath = SelectedPath;
      dialog.ShowNewFolderButton = ShowNewFolderButton;
      return dialog;
    }
  }

  internal static class WindowExtensions
  {
    public static System.Windows.Forms.IWin32Window AsWin32Window(this Window window)
    {
      return new Wpf32Window(window);
    }
  }

  internal class Wpf32Window : System.Windows.Forms.IWin32Window
  {
    public Wpf32Window(Window window)
    {
      Handle = new WindowInteropHelper(window).Handle;
    }

    #region IWin32Window Members

    public IntPtr Handle { get; private set; }

    #endregion
  }

然后,在要使用FolderBrowser导入IFolderBrowserDialog的位置制作VM/命令.在应用程序中,IFolderBrowserDialog.ShowDialog显示对话框.在单元测试中,我们模拟了IFolderBrowserDialog,以便可以验证是否使用正确的参数调用了它,并且/或者将选定的文件夹发送回sut,以便测试可以继续.

Then we make the VM/Command where we want to use the FolderBrowser import IFolderBrowserDialog. In application, IFolderBrowserDialog.ShowDialog shows the dialog. In unit test, we mock IFolderBrowserDialog so we can verify that it was called with correct parameters and/or send the selected folder back to the sut so that the test can continue.

这篇关于如何通过MVVM在WPF应用程序中使用FolderBrowserDialog的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆