如何使用 WPF 应用程序中的 FolderBrowserDialog
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/315164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use a FolderBrowserDialog from a WPF application
提问by Craig Shearer
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 - 没什么特别的。我不太关心它是否具有 Windows 窗体外观。
However, when I call ShowDialog, I want to pass the owner window which is an IWin32Window. How do I get this from my WPF control?
但是,当我调用 ShowDialog 时,我想传递一个 IWin32Window 的所有者窗口。我如何从我的 WPF 控件中获取它?
Actually, does it matter? If I run this code and use the ShowDialog overload with no parameters it works fine. Under what circumstances do I need to pass the owner window?
其实,重要吗?如果我运行此代码并使用不带参数的 ShowDialog 重载,则它可以正常工作。什么情况下需要通过owner窗口?
Thanks,
谢谢,
Craig
克雷格
回答by Craig Shearer
And here's my final version.
这是我的最终版本。
public static class MyWpfExtensions
{
public static System.Windows.Forms.IWin32Window GetIWin32Window(this System.Windows.Media.Visual visual)
{
var source = System.Windows.PresentationSource.FromVisual(visual) as System.Windows.Interop.HwndSource;
System.Windows.Forms.IWin32Window win = new OldWindow(source.Handle);
return win;
}
private class OldWindow : System.Windows.Forms.IWin32Window
{
private readonly System.IntPtr _handle;
public OldWindow(System.IntPtr handle)
{
_handle = handle;
}
#region IWin32Window Members
System.IntPtr System.Windows.Forms.IWin32Window.Handle
{
get { return _handle; }
}
#endregion
}
}
And to actually use it:
并实际使用它:
var dlg = new FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dlg.ShowDialog(this.GetIWin32Window());
回答by Jobi Joy
If you specify Owner, you will get a Modal dialog over the specified WPF window.
如果您指定所有者,您将在指定的 WPF 窗口上看到一个模态对话框。
To get WinForms compatible Win32 window create a class implements IWin32Window like this
为了让 WinForms 兼容 Win32 窗口,创建一个类实现 IWin32Window 像这样
public class OldWindow : System.Windows.Forms.IWin32Window
{
IntPtr _handle;
public OldWindow(IntPtr handle)
{
_handle = handle;
}
#region IWin32Window Members
IntPtr System.Windows.Forms.IWin32Window.Handle
{
get { return _handle; }
}
#endregion
}
And use an instance of this class at your WinForms
并在您的 WinForms 中使用此类的实例
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle; // 'this' means WPF Window
folderBrowserDialog.ShowDialog(new OldWindow(mainWindowPtr));
回答by Branko Dimitrijevic
I realize this is an old question, but here is an approach which might be slightly more elegant (and may or may not have been available before)...
我意识到这是一个老问题,但这里有一种可能更优雅的方法(以前可能有也可能没有)......
using System;
using System.Windows;
using System.Windows.Forms;
// ...
/// <summary>
/// Utilities for easier integration with WinForms.
/// </summary>
public static class WinFormsCompatibility {
/// <summary>
/// Gets a handle of the given <paramref name="window"/> and wraps it into <see cref="IWin32Window"/>,
/// so it can be consumed by WinForms code, such as <see cref="FolderBrowserDialog"/>.
/// </summary>
/// <param name="window">
/// The WPF window whose handle to get.
/// </param>
/// <returns>
/// The handle of <paramref name="window"/> is returned as <see cref="IWin32Window.Handle"/>.
/// </returns>
public static IWin32Window GetIWin32Window(this Window window) {
return new Win32Window(new System.Windows.Interop.WindowInteropHelper(window).Handle);
}
/// <summary>
/// Implementation detail of <see cref="GetIWin32Window"/>.
/// </summary>
class Win32Window : IWin32Window { // NOTE: This is System.Windows.Forms.IWin32Window, not System.Windows.Interop.IWin32Window!
public Win32Window(IntPtr handle) {
Handle = handle; // C# 6 "read-only" automatic property.
}
public IntPtr Handle { get; }
}
}
Then, from your WPF window, you can simply...
然后,从您的 WPF 窗口,您可以简单地...
public partial class MainWindow : Window {
void Button_Click(object sender, RoutedEventArgs e) {
using (var dialog = new FolderBrowserDialog()) {
if (dialog.ShowDialog(this.GetIWin32Window()) == System.Windows.Forms.DialogResult.OK) {
// Use dialog.SelectedPath.
}
}
}
}
Actually, does it matter?
其实,重要吗?
I'm not sure if it matters in this case, but generally, you should tell Windows what is your window hierarchy, so if a parent window is clicked while child window is modal, Windows can provide a visual (and possibly audible) clue to the user.
我不确定在这种情况下是否重要,但一般来说,您应该告诉 Windows 您的窗口层次结构是什么,因此如果在子窗口处于模态时单击父窗口,Windows 可以提供视觉(可能是听觉)线索用户。
Also, it ensures the "right" window is on top when there are multiple modal windows (not that I'm advocating such UI design). I've seen UIs designed by a certain multi-billion dollar corporation (which shell remain unnamed), that hanged simply because one modal dialog got "stuck" underneath another, and user had no clue it was even there, let alone how to close it.
此外,当有多个模态窗口时,它可以确保“正确”的窗口位于顶部(不是我提倡这样的 UI 设计)。我见过由某个价值数十亿美元的公司设计的用户界面(其外壳仍未命名),仅仅因为一个模态对话框“卡在”另一个模态对话框下方,而用户不知道它甚至在那里,更不用说如何关闭了它。
回答by Craig Shearer
OK, figured it out now - thanks to Jobi whose answer was close, but not quite.
好的,现在想通了 - 感谢 Jobi,他的回答很接近,但并不完全。
From a WPF application, here's my code that works:
从 WPF 应用程序中,这是我的工作代码:
First a helper class:
首先是一个助手类:
private class OldWindow : System.Windows.Forms.IWin32Window
{
IntPtr _handle;
public OldWindow(IntPtr handle)
{
_handle = handle;
}
#region IWin32Window Members
IntPtr System.Windows.Forms.IWin32Window.Handle
{
get { return _handle; }
}
#endregion
}
Then, to use this:
然后,要使用这个:
System.Windows.Forms.FolderBrowserDialog dlg = new FolderBrowserDialog();
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
System.Windows.Forms.IWin32Window win = new OldWindow(source.Handle);
System.Windows.Forms.DialogResult result = dlg.ShowDialog(win);
I'm sure I can wrap this up better, but basically it works. Yay! :-)
我相信我可以更好地完成它,但基本上它是有效的。好极了!:-)
回答by Bruno
//add a reference to System.Windows.Forms.dll
public partial class MainWindow : Window, System.Windows.Forms.IWin32Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
var fbd = new FolderBrowserDialog();
fbd.ShowDialog(this);
}
IntPtr System.Windows.Forms.IWin32Window.Handle
{
get
{
return ((HwndSource)PresentationSource.FromVisual(this)).Handle;
}
}
}
回答by user2307482
VB.net translation
VB.net 翻译
Module MyWpfExtensions
Public Function GetIWin32Window(this As Object, visual As System.Windows.Media.Visual) As System.Windows.Forms.IWin32Window
Dim source As System.Windows.Interop.HwndSource = System.Windows.PresentationSource.FromVisual(Visual)
Dim win As System.Windows.Forms.IWin32Window = New OldWindow(source.Handle)
Return win
End Function
Private Class OldWindow
Implements System.Windows.Forms.IWin32Window
Public Sub New(handle As System.IntPtr)
_handle = handle
End Sub
Dim _handle As System.IntPtr
Public ReadOnly Property Handle As IntPtr Implements Forms.IWin32Window.Handle
Get
End Get
End Property
End Class
End Module
回答by user2307482
Why not using the built in WindowInteropHelper class (see namespace System.Windows.Interop). This class already impelements the IWin32Window ;)
为什么不使用内置的 WindowInteropHelper 类(请参阅命名空间 System.Windows.Interop)。这个类已经实现了 IWin32Window ;)
So you can forget about the "OldWindow class" ... the usage stays the same
所以你可以忘记“OldWindow类”......用法保持不变
回答by Andy
The advantage of passing an owner handle is that the FolderBrowserDialog will not be modal to that window. This prevents the user from interacting with your main application window while the dialog is active.
传递所有者句柄的优点是 FolderBrowserDialog 不会是该窗口的模态。这可以防止用户在对话框处于活动状态时与您的主应用程序窗口进行交互。
回答by jageall
回答by Shangwu
Here is a simple method.
这里有一个简单的方法。
System.Windows.Forms.NativeWindow winForm;
public MainWindow()
{
winForm = new System.Windows.Forms.NativeWindow();
winForm.AssignHandle(new WindowInteropHelper(this).Handle);
...
}
public showDialog()
{
dlgFolderBrowser.ShowDialog(winForm);
}