From bc8002caf201ad84c408c1b67f0b6895f373a78c Mon Sep 17 00:00:00 2001 From: Violet Hansen Date: Tue, 10 Dec 2024 13:43:37 +0200 Subject: [PATCH] Improved MenuFlyout It not longer automatically closes when a single item is selected on it --- .../CustomUIElements/MenuFlyoutV2.cs | 72 +++++++++++++++++++ .../ViewCurrentPolicies.xaml | 6 +- .../ViewCurrentPolicies.xaml.cs | 21 +++++- 3 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 AppControl Manager/CustomUIElements/MenuFlyoutV2.cs diff --git a/AppControl Manager/CustomUIElements/MenuFlyoutV2.cs b/AppControl Manager/CustomUIElements/MenuFlyoutV2.cs new file mode 100644 index 000000000..5b897482e --- /dev/null +++ b/AppControl Manager/CustomUIElements/MenuFlyoutV2.cs @@ -0,0 +1,72 @@ +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace AppControlManager.CustomUIElements +{ + /// + /// A custom implementation of MenuFlyout that prevents the flyout from automatically closing + /// when a menu item is selected. This is achieved by tracking pointer interactions on the flyout items. + /// + internal sealed partial class MenuFlyoutV2 : MenuFlyout + { + /// + /// Initializes a new instance of the class. + /// Subscribes to the Opened event to attach pointer event handlers to the menu items. + /// + internal MenuFlyoutV2() + { + // Attach the handler for the Opened event to initialize event listeners for pointer interactions on menu items + Opened += MenuFlyoutV2_Opened; + } + + /// + /// Property to track whether the user's pointer is currently over any menu item in the flyout. + /// + internal bool IsPointerOver { get; set; } + + /// + /// Event handler for when the flyout is opened. + /// Attaches PointerEntered and PointerExited event handlers to each item in the flyout. + /// + /// The source of the event (the flyout itself). + /// The event data. + private void MenuFlyoutV2_Opened(object? sender, object e) + { + // Loop through each menu item in the flyout's Items collection + foreach (MenuFlyoutItemBase menuItem in Items) + { + // Ensure existing handlers are removed to avoid multiple attachments + // (to prevent duplicate event triggers if the flyout is opened multiple times) + menuItem.PointerEntered -= MenuItem_PointerEntered; + menuItem.PointerEntered += MenuItem_PointerEntered; + + menuItem.PointerExited -= MenuItem_PointerExited; + menuItem.PointerExited += MenuItem_PointerExited; + } + } + + /// + /// Event handler for when the pointer enters a menu item in the flyout. + /// This sets the IsPointerOver property to true, indicating that the pointer is interacting with the menu. + /// + /// The menu item that the pointer entered. + /// The event data for the pointer interaction. + private void MenuItem_PointerEntered(object sender, PointerRoutedEventArgs e) + { + // Set IsPointerOver to true, indicating the pointer is inside the flyout + IsPointerOver = true; + } + + /// + /// Event handler for when the pointer exits a menu item in the flyout. + /// This sets the IsPointerOver property to false, indicating that the pointer is no longer interacting with the menu. + /// + /// The menu item that the pointer exited. + /// The event data for the pointer interaction. + private void MenuItem_PointerExited(object sender, PointerRoutedEventArgs e) + { + // Set IsPointerOver to false, indicating the pointer has left the flyout + IsPointerOver = false; + } + } +} diff --git a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml index 51c5e443c..48790a93f 100644 --- a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml +++ b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml @@ -3,6 +3,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AppControlManager.Pages" + xmlns:customUI="using:AppControlManager.CustomUIElements" xmlns:AppControlManager="using:AppControlManager" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -44,7 +45,8 @@ - + + @@ -70,7 +72,7 @@ - + diff --git a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs index 5812a4df0..a8e6842a3 100644 --- a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs +++ b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs @@ -1,8 +1,7 @@ -using AppControlManager.Logging; -using AppControlManager.SiPolicy; using CommunityToolkit.WinUI.UI.Controls; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Navigation; using System; using System.Collections.Generic; @@ -14,6 +13,7 @@ namespace AppControlManager.Pages { + public sealed partial class ViewCurrentPolicies : Page { // To store the policies displayed on the DataGrid @@ -559,5 +559,22 @@ private static string ConvertRowToText(CiPolicyInfo row) } +#pragma warning disable CA1822 + + /// + /// Event handler to prevent the MenuFlyout to automatically close immediately after selecting a checkbox or any button in it + /// + /// + /// + private void MenuFlyout_Closing(FlyoutBase sender, FlyoutBaseClosingEventArgs args) + { + if (sender is CustomUIElements.MenuFlyoutV2 { IsPointerOver: true }) + { + args.Cancel = true; + } + } + +#pragma warning restore CA1822 + } }