かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

WPF の Window が開いていれば前面に表示する

Ito Blogで紹介されていたWPF の Window が開いていれば前面に表示するですが、自分ならこんなふうに実装するかなぁというのが思いついたのでメモがてらコードを置いておきます。

とりあえず、Applicationクラスが現在開かれているWindowを管理しているので、そこから同じ型のものが含まれるかどうか?というのを判断基準にしてます。
コードは以下のようになります。

namespace SingleWindowsSample
{
    using System;
    using System.Linq;
    using System.Windows;

    public static class WindowManager
    {
        public static void ShowOrActivate<TWindow>()
            where TWindow : Window, new()
        {
            // 対象Windowが開かれているか探す
            var window = Application.Current.Windows.OfType<TWindow>().FirstOrDefault();
            if (window == null)
            {
                // 開かれてなかったら開く
                window = new TWindow();
                window.Show();
            }
            else
            {
                // 既に開かれていたらアクティブにする
                window.Activate();
            }
        }

        // newでインスタンスが作れない時用
        public static void ShowOrActivate<TWindow>(Func<TWindow> factory)
            where TWindow : Window
        {
            // 対象Windowが開かれているか探す
            var window = Application.Current.Windows.OfType<TWindow>().FirstOrDefault();
            if (window == null)
            {
                // 開かれてなかったら開く
                window = factory();
                window.Show();
            }
            else
            {
                // 既に開かれていたらアクティブにする
                window.Activate();
            }
        }
    }
}

使う側は、以下のような感じで使います。

// 単純にnewでインスタンス化できるWindowの場合
WindowManager.ShowOrActivate<Window1>();

// ラムダ式で任意のインスタンス生成方法を指定する場合
WindowManager.ShowOrActivate<Window1>(() => new Window1());


当然のことですが、ItoさんのBlogで書いてある方法のほうがパフォーマンスはいいと思います。ただ、個人的には同時に開くWindowの数なんてたかが知れているので、この方法でも開かれているウィンドウを走査するのがボトルネックになることはないかなぁと思います。