10

I am using ShowDialog() with WindowStyle = WindowStyle.SingleBorderWindow; to open a modal window in my WPF (MVVM) application, but it lets me navigate to parent window using the Windows taskbar (Windows 7).

I've found an answer here: WPF and ShowDialog() but it isn't suitable for me because I don't need an "always on top" tool window.

Thanks in advance

Community
  • 1
  • 1
Oszkar
  • 1,603
  • 3
  • 15
  • 17

7 Answers7

12

Try setting the Owner property of the dialog. That should work.

Window dialog = new Window();
dialog.Owner = mainWindow;
dialog.ShowDialog();

Edit: I had a similar problem using this with MVVM. You can solve this by using delegates.

public class MainWindowViewModel
{
    public delegate void ShowDialogDelegate(string message);
    public ShowDialogDelegate ShowDialogCallback;

    public void Action()
    {
        // here you want to show the dialog
        ShowDialogDelegate callback = ShowDialogCallback;
        if(callback != null)
        {
            callback("Message");
        }
    }
}

public class MainWindow
{
    public MainWindow()
    {
        // initialize the ViewModel
        MainWindowViewModel viewModel = new MainWindowViewModel();
        viewModel.ShowDialogCallback += ShowDialog;
        DataContext = viewModel;
    }

    private void ShowDialog(string message)
    {
        // show the dialog
    }
}
MatthiasG
  • 4,434
  • 3
  • 27
  • 47
  • 2
    Thank you, the idea is good. The only problem at this point is that in the ViewModel I have no information of the View. I tried the `App.Current.MainWindow` and it works but not the nicest solution. Maybe I should reconsider the structure of my MVVM pattern. – Oszkar Mar 25 '12 at 08:11
  • 1
    I added a possible solution for the MVVM issue. – MatthiasG Mar 25 '12 at 11:34
  • 1
    @Oszkar I used `Application.Current.MainWindow` (Application instead of App) and, since it is static - I guess - it worked fine without distressing MVVM. – heltonbiker Feb 24 '17 at 12:38
5

I had this problem but as the Window was being opened from a view model I didn't have a reference to the current window. To get round it I used this code:

var myWindow = new MyWindowType();
myWindow.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);

You can use: myWindow.Owner = Application.Current.MainWindow;

However, this method causes problems if you have three windows open like this:

MainWindow
   |
   -----> ChildWindow1

               |
               ----->  ChildWindow2

Then setting ChildWindow2.Owner = Application.Current.MainWindow will set the owner of the window to be its grandparent window, not parent window.

GrandMasterFlush
  • 6,269
  • 19
  • 81
  • 104
1

When the parent window makes (and shows) the child window, that is where you need to set the owner.

public partial class MainWindow : Window
{

    private void openChild()
    {
        ChildWindow child = new ChildWindow ();
        child.Owner = this; // "this" is the parent
        child.ShowDialog();
    }
 }

Aditionally, if you don't want an extra taskbar for all the children... then

<Window x:Class="ChildWindow"           
        ShowInTaskbar="False" >
</Window>
00jt
  • 2,818
  • 3
  • 25
  • 29
  • What if `this` isn't a Window? I'm running WPF from MFC and so I have no Application or main Window. – Jim Balter Jun 10 '14 at 07:50
  • What are you trying to open? Just display a dialog? If you aren't trying to attach a dialog to a window, i don't understand your question. – 00jt Jul 09 '14 at 21:03
  • As I said, "from MFC" ... MFC classes aren't derived from WPF's Window. I recently discovered WindowInteropHelper.Owner ... although even with that we end up with hidden modal dialogs. – Jim Balter Jul 10 '14 at 04:03
  • sorry, missed that. I'm not sure how to make a WPF's owner be a MFC . – 00jt Jul 11 '14 at 16:01
1

Much of the reason for the MVVM pattern is so that your interaction logic can be unit tested. For this reason, you should never directly open a window from the ViewModel, or you'll have dialogs popping up in the middle of your unit tests.

Instead, you should raise an event that the View will handle and open a dialog for you. For example, see this article on Interaction Requests: https://msdn.microsoft.com/en-us/library/gg405494(v=pandp.40).aspx#sec12

hypehuman
  • 1,290
  • 2
  • 18
  • 37
1

The problem seems to be related to Window.Owner, and indeed if you judge by previous knowledge that you might have of the Win32 API and WinForms, a missing owner would be the typical cause of such a problem, but as many have pointed out, in the case of WPF that's not it. Microsoft keeps changing things to keep things interesting.

In WPF you can have a dialog with a specific owner and you can still have the dialog appear in the taskbar. Because why not. And that's the default behavior. Because why not. Their rationale is that modal dialogs are not kosher anymore, so you should not be using them; you should be using modeless dialogs, which make sense to show as separate taskbar icons, and in any case the user can then decide whether they want to see different app windows as separate icons, or whether they want to see them grouped.

So, they are trying to enforce this policy with complete disregard to anyone who might want to go against their guidelines and create a modal dialog. So, they force you to explicitly state that you do not want a taskbar icon to appear for your dialog.

To fix this problem, do the following in the constructor of your view class:

ShowInTaskbar = false;

(This may happen right after InitializeComponent();

This is equivalent to Xcalibur37's answer, though the way I figure things, since WPF forces you to have both a .cs file and a .xaml file, you might as well put things that are unlikely to change in the .cs file.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
0

Even if this post is a bit old, I hope it is OK that I post my solution. All the above results are known to me and did not exactly yield the desired result.

I am doing it for the other googlers :)

Lets say f2 is your window that you want to display on top of f1 :

f2.Owner = Window.GetWindow(this);
f2.ShowDialog();

That's it , I promise it will not disappear !

HTH Guy

Guy Cohen
  • 689
  • 1
  • 9
  • 25
0

Add "ShowInTaskbar" and set it to false.

Xcalibur37
  • 2,305
  • 1
  • 17
  • 20