Question

I´m working on a WPF-Application. In it´s file-based I/O-Functions I´m catching Exceptions that are thrown when a file is used by another process. In that case a Messagebox should appear with retry/cancel-options. As far as I figured out, there is no such Messagebox in WPF (Windows.MessageBox), so I´m trying to use a Windows.Forms.Messagebox, but it behaves strangely:

When I call it once (with just OK-Button-Option just for testing)...

System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);

...it appears for a millisecond, then disappears.

When I call it twice...

System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);
System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);

...the second Messagebox stays visible as expected until you click "Ok".

I already tried to use "null" as a parameter for the IWin32Window, but it had no effect. Also I tried to pass the WPF-Mainwindow as a parameter but (of course) it´s the wrong type.

Any suggestions?

Was it helpful?

OTHER TIPS

You can use the Popup control to create any dialog that you want.

MSDN

An example

More examples

It doesn't make a lot of sense that the WinForms message box function isn't working in a WPF application. After all, both APIs call the native Win32 MessageBox function.

The issue might be related to the code in the System.Windows.Forms.MessageBox implementation that attempts to disable all of the windows in preparation for displaying a modal dialog. That might not be interacting properly with some of the WPF plumbing, producing some strange behavior. Speculation, of course; I'm not an expert on WPF.

I did, however, peruse the System.Windows.MessageBox implementation in the reference source, and couldn't help but notice that it omits the code that the WinForms implementation has for disabling other windows. It just calls the Win32 MessageBox function directly, which is what I would have done in either case. I'm sure the WinForms team has a good reason for their decision, I just don't know what it is.

So what to do? Like everyone else, my first inclination would be to tell you to use the MessageBox function specifically designed for use in WPF applications. But like you said, it doesn't support the Retry or Cancel buttons. There's no good reason why not, the WPF team just doesn't appear to have exposed access to this functionality. Maybe the UI folks at Microsoft are trying to discourage use of Retry and Cancel buttons? Anyway, you can get what you want by P/Invoking the Win32 MessageBox function:

    private const int MB_RETRYCANCEL   = 0x00000005L;

    private const int IDCANCEL         = 2;
    private const int IDRETRY          = 4;

    private const int MB_DEFBUTTON1  = 0x00000000;
    private const int MB_DEFBUTTON2  = 0x00000100;

    private const int MB_ICONERROR       = 0x00000010;
    private const int MB_ICONWARNING     = 0x00000030; 
    private const int MB_ICONINFORMATION = 0x00000040;

    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern int MessageBox(HandleRef hWnd,
                                        string text,
                                        string caption,
                                        int type);

and calling it yourself, directly:

switch (MessageBox(new HandleRef(null, owner),  // your owner window
                   "My Message Text",           // your message
                   "Message",                   // the dialog box title/caption
                   MB_RETRYCANCEL | MB_ICONERROR | MB_DEFBUTTON1))
{
    case IDRETRY:
    {
        // ...
    }
    case IDCANCEL:
    {
        // ...
    }
    default:
    {
        throw new NotSupportedException("MessageBox is displayed only with Retry and Cancel buttons; any other response is not supported and should be impossible.");
    }
}

result will be either IDRETRY or IDCANCEL. You can specify whatever icon you want, or omit it to have no icon. And MB_DEFBUTTON1 specifies that the Retry button is the default. Use MB_DEFBUTTON2 to make the Cancel button the default.

But really, you should be using the TaskDialog, not a MessageBox. I figured WPF would have a wrapper for this, but a web search indicates it does not. The Windows API Code Pack does, obsoleted or not.

Try System.Windows.MessageBox instead of System.Windows.Forms.MessageBox . System.Windows.MessageBox is the WPF version.

It is Part of the PresentationFramework.dll file.

Source: MSDN

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top