Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Custom ShowDialog() method for WPF

0.00/5 (No votes)
29 Apr 2011 1  
Custom ShowDialog() method for WPF
In one of my articles, I have considered DispatcherFrame. I tried to look in-depth of DispatcherFrame, showed some IL sources of .NET and tried to explain what it is.

While reading MSDN about the threading model, I saw a section, which said that PushFrame() can be used to create something like WPF dialog windows. That window takes control after calling ShowDialog() and doesn’t return control to the parent window until closed. So, I wondered, how to create such window?
During this article, you will also learn how to get full control on process of showing and hiding custom modal windows and how to control blocking and unblocking of another windows.

Custom ShowModal()

For the first, I tried to open a new window in a separate thread. It works! But when I clicked on suspended parent window 5-10 times, that window gets “Not responded”. Not good!

I really wondered how to block parent window, but prevent it from suspension. I thought about how to use DispatcherFrame here. Obviously, if the main thread is blocked, then the parent window will be also blocked, because of blocked dispatcher. So, there is no way to use PushFrame in such a solution.

After that, I decided to use Reflector to see how ShowDialog() is implemented in WPF. So, what do I see? WINAPI is used there to block each window in the current thread.

[SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", EntryPoint="EnableWindow", CharSet=CharSet.Auto)] 
public static extern bool IntEnableWindowNoThrow(HandleRef hWnd, bool enable); 


This method is called for each window with enable = false. As you guessed, the solution comes closer. To implement my own ShowModal(), I should perform following steps:

  • Block parent window
  • Add event handler on modal closed and unblock parent window inside this handler
  • Show modal window and call PushFrame()

That’s it!

[DllImport("user32")]
internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable);

public void ShowModal()
{
    IntPtr handle = (new WindowInteropHelper(Application.Current.MainWindow)).Handle;
    EnableWindow(handle, false);

    DispatcherFrame frame = new DispatcherFrame();

    this.Closed += delegate
    {
        EnableWindow(handle, true);
        frame.Continue = false;
    };

    Show();
    Dispatcher.PushFrame(frame);
}


First, we define extern method which uses WINAPI to enable/disable windows. Exactly that method is used in WPF ShowDialog(). Then we blocks window, show modal and push new DispatcherFrame.

Why do we have to use PushFrame() here? The answer is to prevent returning from ShowModal() method. When a new frame is pushed, the main loop is suspended and a new loop starts. This new loop processes system messages and execution point in main loop doesn’t go forward. When modal closes, DispatcherFrame.Continue = false, and this frame is exited. And after that, the application is back to normal flow.
This approach has no obvious advantages compared to ShowDialog() method. Dialog behaviour is totally the same.

But there is one benefit that can be very useful in some cases. The benefit provided by this method is full control on blocking and unblocking windows from modal window. Say, what if you needed to block only 2 of 4 active windows? Or unblock window while dialog is shown? It could be problematic with classic ShowDialog() method. Of course, you can use WinAPI, but this is not so obvious as with custom ShowModal() method.

Also, you can put windows blocking and unblocking command anywhere. Just put PushFrame() and frame.Continue = false, to places of code, where you want to stop or continue default application flow, and you will get it. It can be useful if you want to continue main frame flow without closing of modal window or otherwise don't continue it after closing.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here