3

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?

tafkab76
  • 465
  • 1
  • 6
  • 18
  • 2
    There *is* WPF equivalent to `MessageBox`. See: http://stackoverflow.com/questions/3830228/is-there-a-messagebox-equivalent-in-wpf – amnezjak May 15 '14 at 08:12
  • Use WPF message box in replacement of windows form message form. – Maverick May 15 '14 at 08:19
  • I´m aware of the System.Windows.Messagebox, but it lacks the retry/cancel-buttons, which I intend to use. – tafkab76 May 15 '14 at 08:33
  • Since rephrasing the message to fit a Yes/No MessageBox seems like 'a lot' of 'work' You could try designing your own custom message box, you know you want to. – sdf May 15 '14 at 08:40
  • @sdf: Of course it´s not a lot of work, but as my scenario is a perfect match for a retry/cancel-option, I would prefer to use such. – tafkab76 May 15 '14 at 08:45
  • Actually I do not understand why everyone is answering with what he *could* do in WPF instead of answering his real question: Why doesn't the Windows Forms message box work in WPF applications? – Thorsten Dittmar May 15 '14 at 08:57
  • @ThorstenDittmar Do you know the answer? Then feel free to do so instead of criticising us for the presenation of alternatives... – M C May 15 '14 at 09:04
  • WinForms and WPF being not very compatible is what we actually expect. Mixing these technologies for such a small task seems like a bad idea in general? Maybe he just needs a WindowsFormsHost or something, I doubt there are a lot of people with expertise in doing stuff like this. – sdf May 15 '14 at 09:06
  • 4
    @MC No I don't - that's why instead of writing just *some* answer I'm keeping my mouth shut. Presenting alternatives is fine - but not as an answer. If I asked you *How much is a flight to Bangkok?* you wouldn't answer *Just go downtown.* just because you don't know, would you? – Thorsten Dittmar May 15 '14 at 09:16

4 Answers4

1

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

MSDN

An example

More examples

Rui
  • 4,847
  • 3
  • 29
  • 35
  • 1
    Just to be clear, though, this is *not* a modal dialog, right? Which is a rather important difference compared to MessageBox. – Cody Gray - on strike May 15 '14 at 10:42
  • You right, it's not *modal*. Maybe this can help: http://bradleach.wordpress.com/2009/02/25/control-level-modal-dialog/. In the comments they describe using a (transparent) rectangle to "disable" interaction with the elements below the "modal dialog". It's a bit of work, but as far as I know, this is the only way to get a custom modal dialog – Rui May 15 '14 at 14:03
1

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.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Thank for the answer and the information on what´s behind Windows.MessageBox and Windows.Forms.Messagebox. Also for the "work-around". I think, I will go the "way of lowest resistance" and use a Windows.MessageBox and rephrase the text so that the given MessageBoxButtons-options make sense. – tafkab76 May 15 '14 at 11:19
  • @tafk Eh, I don't know. From a UX perspective, "Do you want to retry? Yes/No" is nowhere near as clear as buttons explicitly labeled "Retry/Cancel". Studies have repeatedly shown that users don't read message text, they just click on a button to dismiss the message box as quickly as possible. Having the right caption on the button makes all the difference. Which is why TaskDialog, the new API to replace MessageBox, lets you specify completely *custom* button captions. – Cody Gray - on strike May 15 '14 at 11:23
0

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

M C
  • 626
  • 1
  • 11
  • 27
  • I´m aware of the System.Windows.Messagebox, but it lacks the retry/cancel-buttons, which I intend to use. – tafkab76 May 15 '14 at 08:34
  • Can't you rephrase your Message so the available MessageBoxButton options will suffice? – M C May 15 '14 at 08:36
  • Yes, of course. Instead of saying "The file is blocked by another process [retry] [cancel]" I could say "the file is blocked by another process. Retry access? [yes] [no]" or something like that and I will probably do that if there is no other solution. I was just wondering why the Windows.Forms.Messagebox doesn´t work as expected. (I could also search for a customized Windows.Messagebox with retry/cancel-options, I guess). – tafkab76 May 15 '14 at 08:41
0

for everybody with the same question, this thread explained and even solved the problem:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/116bcd83-93bf-42f3-9bfe-da9e7de37546/messagebox-closes-immediately-in-dispatcherunhandledexception-handler?forum=wpf

tafkab76
  • 465
  • 1
  • 6
  • 18