17

次の単純な wpf アプリケーションがあります。

アプリ.xaml:

<Application x:Class="TestWpf2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>

アプリ.xaml.cs:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var parentWindow = new Window();
        parentWindow.Show();

        var childWindow1 = new Window { Owner = parentWindow };
        childWindow1.Show();

        var childWindow2 = new Window { Owner = parentWindow };
        childWindow2.Show();
    }
}

アプリケーションにより、画面に 3 つのウィンドウが表示されます。アプリケーションを実行して 2 つの子ウィンドウを閉じると、親ウィンドウはタスク バーに最小化されます。をコメントアウトしchildWindow2.show()てアプリケーションを実行し、単一の子ウィンドウを閉じると、親ウィンドウはタスクバーに最小化されません。

この問題を回避するには、次のコードを追加します。

childWindow1.Closing += delegate(object sender, CancelEventArgs ex)
{
    (sender as Window).Owner = null;
};

しかし、私はこのようなハックを使用したくありません。なぜこの問題が発生するのかを理解したいのです。

なぜこれが起こるのですか?

4

3 に答える 3

17

これは WPF の文書化されていない機能です (バグ)

このバグは、7 年以上前に Microsoft に報告されています。

非モーダル ウィンドウの上にモーダル ダイアログがあると、メイン ウィンドウが背面に移動します。

WPF チームは最近この問題を確認しましたが、現時点では最も多くの WPF 開発者に影響を与えるバグに焦点を当てているため、この問題に対処する予定はありません。

この文書化されていない機能の動作を少し見てみましょう。

最小化せず、ウィンドウを 1 つ後ろに移動します (デバッグ モードでは、ビジュアル スタジオ ウィンドウの後ろ)。

証明する手順:

  • このアプリケーションを実行します。

  • 他のすべてのウィンドウを最小化します (例: Visual Studio と他のすべてのウィンドウ)。これら 3 つのウィンドウのみを画面に表示します。

  • 両方の子を閉じます。親はまだNormal状態にあります

さらに証明するためにこのコードをテストして StateChangeください。

        protected override void OnStartup(StartupEventArgs e)
        {
            var parentWindow = new Window() { Title = "Parent" };
            parentWindow.StateChanged += (sender, ep)=>
            {
                var state = ((Window)sender).WindowState;
            };
            parentWindow.Show();

            var childWindow1 = new Window { Owner = parentWindow, Title = "Child1" };
            childWindow1.Show();

            var childWindow2 = new Window { Owner = parentWindow, Title = "Child2" };
            childWindow2.Show();
        }

TopMost であることで、このような事態を防ぐことができます

親ウィンドウが TopMost の場合、これは発生しません。しかし、多くの場合、これはオプションではありません。

parentWindow.Topmost = true;

回避策

child2 を閉じるときに親をアクティブにします。

childWindow2.Closed += (a, b) => { parentWindow.Activate(); };
于 2017-06-13T13:17:17.327 に答える
3

これは、所有者セットで子ウィンドウが表示されると、親ウィンドウを使用できないためです。子が画面に表示されている間に親ウィンドウにアクセスしようとしても、意味がわかりません。

Owner を指定しない場合、この動作は発生しません。

于 2012-05-25T17:28:16.780 に答える
1

私はこれが起こる原因を解明したことはありません!最後に、子ウィンドウが閉じられた後に呼び出される次のコードを作成しました。

// App inherits from Application, and has a Window property called MainWindow
// and a List<Window> property called OpenWindows.
if (!App.OpenWindows.Any())
    App.ParentWindow.Activate();

そのため、最後の子ウィンドウが閉じられる ( App.OpenWindows.Any()false になる) と、親ウィンドウがアクティブになります。これによりちらつきが発生することはありません (たとえば、メイン ウィンドウが最小化されてから最大化されます)。

これは最善の解決策ではありません。WPF にこの機能がある理由を誰かが説明できることを期待して、この質問を閉じません。

于 2012-11-20T12:09:39.573 に答える