Принудительно закрыть все открытые всплывающие окна из кода - PullRequest
4 голосов
/ 08 октября 2010

Я хочу, чтобы все открытые всплывающие окна (с StaysOpen == false) закрывались из кода.По сути, я хочу смоделировать щелчок мышью пользователя (который закроет всплывающие окна) из кода.

Мне не нужно фактически имитировать щелчок, мне просто нужно поведение, полученное в результате.Я думал о том, чтобы просто пройтись по визуальному дереву в поисках всплывающих окон и закрыть каждое из них, но это не самый чистый подход.

Заранее спасибо за любую помощь или мнения.

Ответы [ 3 ]

9 голосов
/ 08 октября 2010

Всплывающее окно WPF фактически создает новое окно (окно Win32, а не экземпляр WPF Window).Таким образом, вы не можете найти его в коллекции Application.Windows, но вы, вероятно, можете найти его с помощью Win32 API, например EnumChildWindows.

Когда у вас есть дескриптор, вы можете получить егосвязанный HwndSource.Я думаю, что RootVisual из HwndSource - это Popup (не проверял, возможно, вам придется заглянуть глубже в визуальное дерево).

Так что код должен быть похож на это (полностьюне проверено):

public static class PopupCloser
{
    public static void CloseAllPopups()
    {
        foreach(Window window in Application.Current.Windows)
        {
            CloseAllPopups(window);
        }
    }

    public static void CloseAllPopups(Window window)
    {
        IntPtr handle = new WindowInteropHelper(window).Handle;
        EnumChildWindows(handle, ClosePopup, IntPtr.Zero);
    }

    private static bool ClosePopup(IntPtr hwnd, IntPtr lParam)
    {
        HwndSource source = HwndSource.FromHwnd(hwnd);
        if (source != null)
        {
            Popup popup = source.RootVisual as Popup;
            if (popup != null)
            {
                popup.IsOpen = false;
            }
        }
        return true; // to continue enumeration
    }

    private delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

}
1 голос
/ 08 октября 2010

Пройдя по визуальному дереву - это способ сделать это, который никоим образом не зависит от того, как вы их создали.Возможно, есть более понятные способы сделать это, но все они действительно зависят от вашей реализации.

Например, все всплывающие окна в моем приложении обязаны просматривать объекты модели, которые предоставляют какое-то свойство IsOpenчто Popup привязывает к.Если бы мне нужно было реализовать эту функциональность в моем проекте, я бы просто поддерживал коллекцию этих объектов (или метод генератора), который мог бы выполнять итерацию, и устанавливал для IsOpen значение false для каждого.Это, очевидно, не сработает, если вы не создаете свой пользовательский интерфейс, как я.

0 голосов
/ 15 сентября 2014
  1. Объявите где-нибудь статический массив открытых всплывающих окон:

    static List<Popup> openedPopups = new List<Popup>();

  2. Перед открытием всплывающего окна закройте все предварительно открытые всплывающие окна:

    private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // close all before opene popup openedPopups.ForEach(p => p.IsOpen = false); openedPopups.Clear(); // clear opened popus's collection, because they were closed Popup1.IsOpen = true; // open popup I need open now openedPopups.Add(Popup1); // remember it for future close }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...