web-dev-qa-db-ja.com

モーダルダイアログが他のウィンドウの上に表示されない

Window.ShowDialog()を使用してWPF(MVVM)アプリケーションでモーダルウィンドウを開きますが、Windowsタスクバー(Windows 7)を使用して他のウィンドウに移動できます。

これを考慮してください。アプリケーションで3つの非モーダルウィンドウを開いています。現在、これらの1つはWindow.ShowDialog()を使用してモーダルウィンドウを開きます。また、Application.MainWindowモーダルウィンドウの所有者として。これは、MVVMメッセージングを使用しており、メッセージハンドラーが新しいウィンドウを開くのはApp.xaml.cs。ウィンドウはモーダルで開きます-問題はありません。ただし、Windows 7では、タスクバーから他のアプリケーションウィンドウに切り替えることができます。これにより、モーダルウィンドウが別のウィンドウの背後に配置される状況になりますが、これは望ましくありません。

モーダルを開いている限り、他のウィンドウでは何もできませんが、モーダルウィンドウが開いている限り常に最上部に残っているといいでしょう。モーダルが開いているときにタスクバーの切り替えを無効にする方法はありますか?参考-アプリから起動されたすべての開いているウィンドウは、タスクバーに個別のエントリとして表示されます。

前もって感謝します!

24
Pratz

これを基にするコードはありませんが、作成して期待したWindowのいくつかのプロパティを省略したようです ShowDialog to追加の「ダイアログ」セマンティクスを適用します。

Window window = new Window()
{
    Title = "Modal Dialog",
    ShowInTaskbar = false,               // don't show the dialog on the taskbar
    Topmost = true,                      // ensure we're Always On Top
    ResizeMode = ResizeMode.NoResize,    // remove excess caption bar buttons
    Owner = Application.Current.MainWindow,
};

window.ShowDialog();
60
user7116

Windowのownerプロパティを呼び出しウィンドウに設定するだけです。次に、タスクバーでWPFアプリケーションをアクティブ化すると、MainWindowだけでなくモーダルの子ウィンドウもアクティブ化され、前面に表示されます。

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
11
Bitbauer

TopmostをTrue(Topmost = True)に設定すると、ダイアログがシステム内のすべてのウィンドウの最上部に表示されます(アプリケーション内だけでなく)。

そのため、メインウィンドウでActivatedイベントを登録してみることができます。

Activated += WindowActivated;

アプリケーションの別のメインウィンドウがアクティブになるたびに、モーダルダイアログの所有者ウィンドウをアクティブにします。

private void WindowActivated(object sender, EventArgs e)
{
    Window window = Application.Current.Windows.OfType<YourMainWindow>().FirstOrDefault(p => p != this && !p.IsActive && p.OwnedWindows.Count > 0);
    if (window != null)
    {
        window.Activate();
    }
}

この単純なハックは、すべての子ウィンドウがモーダルであることを前提としていますが、より洗練されたロジックを書くことができます。

10
koalix

ここでいくつかの答えを組み合わせて使用​​しました。受け入れられた答えは最初は役に立ちましたが、他の人々がTopmost = trueは、ウィンドウが常に実行中の他のアプリケーションの上にあることを意味します。私の解決策はこれでした:

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

私は最初に使用しました:

myWindow.Owner = Application.Current.MainWindow;

ただし、次のように3つのウィンドウを開いている場合、この方法では問題が発生します。

MainWindow
   |
   -----> ChildWindow1

               |
               ----->  ChildWindow2

次に、ChildWindow2.Owner = Application.Current.MainWindowは、ウィンドウの所有者を親ウィンドウではなく、祖父母ウィンドウに設定します。

速度を上げるために、Visual Studioのコードスニペットとして追加しました。以下を[ツール]-> [コードスニペットマネージャ]-> [マイコードスニペット]に追加する場合:

<CodeSnippets
    xmlns="http://schemas.Microsoft.com/VisualStudio/2010/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>MVVM Set owner of page to be current active window</Title>
      <Shortcut>owner</Shortcut>
    </Header>
    <Snippet>
      <Code Language="CSharp">
        <![CDATA[System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

「所有者」と入力してタブキーをダブルタップすると、「Application.CurrentWindows... '自動的に参加します。

3

少し修正しなければなりませんでした。所有者を設定し、ウィンドウをアクティブにする必要がありました。ポップアップウィンドウを確認し、以下のようにウィンドウをアクティブにします。

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }
1
DiAgo