The power to close all open pop-ups from code

I want to call all open popups (with StaysOpen == false) to close the code. Basically, I want the user to be able to click the mouse (which closed the pop-ups) from the code.

I don’t need to actually simulate a click, I just need to get the result. I was thinking that I was just looking at a visual tree looking for pop-ups and closing each, but that doesn't seem like the cleanest approach.

Thanks in advance for any help or opinions.

+3
source share
3 answers

The WPF popup actually creates a new window (Win32 window, not a WPF instance Window). Therefore, you cannot find it in the collection Application.Windows, but you can probably find it using the Win32 API, for example EnumChildWindows.

Once you have a handle, you can get bound HwndSource. I think that RootVisual HwndSourceis it Popup(not tested, you may need to see deeper in the visual tree).

So, the code should look like this (completely untested):

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

}
+8
source

Walking through a visual tree is a way to do this, which in no way depends on how you created them. There may be much cleaner ways to do this, but they all really depend on your implementation.

, , - IsOpen, Popup. , ( ), , IsOpen false . , , , .

+1
  • - :

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

  • :

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

0

Source: https://habr.com/ru/post/1768510/


All Articles