如何在使用MVVM的WPF应用程序中使用FolderBrowserDialog

11 浏览
0 Comments

如何在使用MVVM的WPF应用程序中使用FolderBrowserDialog

我正试图从我的WPF应用程序中使用FolderBrowserDialog - 没什么花哨的。我并不在乎它看起来像Windows Forms。

我找到了一个适当答案的问题(如何在WPF应用程序中使用FolderBrowserDialog),只是我正在使用MVVM。

这个是我“实现”的答案,只是我无法获取窗口对象,我只是调用ShowDialog()而没有任何参数。

问题是这样的:

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

在我的ViewModel中,this没有GetIWin32Window()方法让我获取窗口上下文。

有什么办法让这个工作吗?

0
0 Comments

问题的出现原因:

在WPF中,使用MVVM模式开发应用程序时,需要在View中使用FolderBrowserDialog对话框来选择文件夹路径。然而,WPF并没有直接提供FolderBrowserDialog控件,而是使用了WinForms中的FolderBrowserDialog控件。因此,需要编写一个自定义的行为(behavior)来实现在WPF应用程序中使用FolderBrowserDialog。

解决方法:

1. 首先,需要创建一个名为FolderDialogBehavior的行为类,继承自Behavior

0
0 Comments

在WPF应用程序中使用MVVM模式时,如何使用FolderBrowserDialog是一个常见的问题。下面是该问题的原因和解决方法。

问题的原因是,WPF应用程序中没有直接使用FolderBrowserDialog的方法。而FolderBrowserDialog是一个Windows Forms控件,与WPF不兼容。因此,需要找到一种方法来在MVVM模式下使用FolderBrowserDialog。

解决方法有两种。第一种方法是使用不需要窗口参数的ShowDialog方法。代码如下:

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

第二种方法是将应用程序的主窗口作为FolderBrowserDialog的拥有窗口参数。代码如下:

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

第二种方法可能不太符合MVVM模式的规范。可以参考Dr. ABT在这个问题中的答案,通过在ViewModel中注入一个指向View的指针的方式来实现对View的访问。这种技术允许在ViewModel中访问对应的View,如果确实希望将View作为FolderBrowserDialog的拥有者,可以使用这种方法。

此外,还可以定义一个接口并封装FolderBrowserDialog,以实现对话框的使用。以下是一个示例代码:

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);
}
[Export(typeof(IFolderBrowserDialog))]
[PartCreationPolicy(CreationPolicy.NonShared)]
internal class WindowsFormsFolderBrowserDialog : IFolderBrowserDialog
{
  //...
}
internal static class WindowExtensions
{
  //...
}
internal class Wpf32Window : System.Windows.Forms.IWin32Window
{
  //...
}

在需要使用FolderBrowserDialog的ViewModel/Command中导入IFolderBrowserDialog。在应用程序中,调用IFolderBrowserDialog.ShowDialog方法显示对话框。在单元测试中,可以使用IFolderBrowserDialog的模拟对象来验证调用参数是否正确,或者将所选文件夹返回给SUT以便继续测试。

这样,就可以在WPF应用程序中使用FolderBrowserDialog,并符合MVVM模式的要求。

0
0 Comments

问题的出现原因:

这个问题的出现是因为在WPF应用程序中使用FolderBrowserDialog时,需要将窗口的句柄传递给FolderBrowserDialog,但是在MVVM模式下,窗口的句柄是无法直接访问的,因此需要找到一种解决方法。

解决方法:

解决方法是通过创建一个依赖属性来公开窗口的句柄,然后将该句柄传递给FolderBrowserDialog。具体步骤如下:

1. 在视图中创建一个依赖属性,用于公开窗口的句柄。

public static readonly DependencyProperty WindowHandleProperty =
    DependencyProperty.Register("WindowHandle", typeof(System.Windows.Forms.IWin32Window), typeof(MainWindow), new PropertyMetadata(null));
public System.Windows.Forms.IWin32Window WindowHandle
{
    get { return (System.Windows.Forms.IWin32Window)GetValue(WindowHandleProperty); }
    set { SetValue(WindowHandleProperty, value); }
}

2. 在窗口加载时,使用之前链接的问题中提供的扩展方法获取窗口的句柄,并将其绑定到依赖属性上。

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    var binding = new Binding();
    binding.Path = new PropertyPath("WindowHandle");
    binding.Mode = BindingMode.OneWayToSource;
    SetBinding(WindowHandleProperty, binding);
    WindowHandle = this.GetIWin32Window();
}

3. 在ViewModel中创建一个与视图中的依赖属性对应的属性,用于接收窗口的句柄。

private System.Windows.Forms.IWin32Window _windowHandle; 
public System.Windows.Forms.IWin32Window WindowHandle
{
    get
    {
        return _windowHandle;
    }
    set
    {
        if (_windowHandle != value)
        {
            _windowHandle = value;
            RaisePropertyChanged("WindowHandle");
        }
    }
}

这种解决方法的好处是不需要硬编码将一个ViewModel与一个特定的View配对。如果在多个View中使用相同的ViewModel,它应该能正常工作。如果创建了一个新的View但没有实现依赖属性,它将使用null句柄进行操作。

注:

另外需要注意的是,是否测试过不提供IWin32Owner参数的情况?对于我来说,它仍然以应用程序的模态对话框自动打开,并阻止用户与应用程序的所有窗口进行交互。您是否需要它做其他事情呢?

0