tags:

views:

11515

answers:

10

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.

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?

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?

Thanks,

Craig

+6  A: 

If you specify Owner, you will get a Modal dialog over the specified WPF window.

To get WinForms compatible Win32 window create a class implements IWin32Window like this

 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

        IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle; // 'this' means WPF Window
        folderBrowserDialog.ShowDialog(new OldWindow(mainWindowPtr));
Jobi Joy
Thanks for this - it's almost right - I'll post an answer below.
Craig Shearer
A: 

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.

Andy
A: 

You should be able to get an IWin32Window by by using PresentationSource.FromVisual and casting the result to HwndSource which implements IWin32Window.

Also in the comments here:

jageall
A: 

Well, I'm thoroughly confused now.

This code doesn't work:

HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
IWin32Window win = source as IWin32Window;

The source comes back with a valid HWndSource object, but in the next line, win is null, despite HWndSource implementing IWin32Window.

Can somebody explain what's going on here?

Craig Shearer
Have you tried the code I pasted, I have used that many times.
Jobi Joy
A: 

OK, I understand this better now. The IWin32Window exists in both System.Windows.Forms and in System.Windows.Interop and on the 2nd line of code I was casting to the System.Windows.Forms.IWin32Window, which HWndSource doesn't implement.

However, the question remains, how do I do this?

Craig Shearer
This is where a new class helps.. Implement IWin32Window on that class and Assign Handle property.. Because IWin32Window is all about its Handle : IntPtr
Jobi Joy
+1  A: 

OK, figured it out now - thanks to Jobi whose answer was close, but not quite.

From a WPF application, here's my code that works:

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! :-)

Craig Shearer
Try the last two lines from my code instead of this 4 lines, I think it will work for you with our the FromVisual call.
Jobi Joy
+10  A: 

And here's my final version. Can somebody please mark this as the answer (once tested, of course!)

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());
Craig Shearer
When I run this code I get a Win32Exception thrown whenever the dialog closes. It doesn't seem to be a problem, and if I just catch it everything seems to work. Do you happen to know why that might be thrown?
Scott Wisniewski
A: 

Why not using the built in WindowInteropHelper class (see namespace System.Windows.Interop). This class already impelements the IWin32Window ;)

So you can forget about the "OldWindow class" ... the usage stays the same

A: 

Para usar los dialogos deben de agregar Refencias System.Windows.Forms de otra forma no saldra

Cristian Antonio ROjas Suarez
Use English dude
Vidar
A: 
//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;
        }
    }
}
Bruno