26

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

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

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

前もって感謝します!

4

5 に答える 5

63

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

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();
于 2011-06-20T21:17:26.123 に答える
13

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

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
于 2012-03-20T16:05:38.510 に答える
12

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();
    }
}

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

于 2012-01-13T07:38:05.533 に答える
3

ここでいくつかの回答を組み合わせて使用​​することになりました。受け入れられた答えは最初は役に立ちましたが、ここの他の人が指摘しているように、設定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...」の部分が自動的に追加されます。

于 2014-03-07T10:46:42.820 に答える
1

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

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }
于 2012-05-05T06:52:15.047 に答える