Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved MenuFlyout #452

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions AppControl Manager/CustomUIElements/MenuFlyoutV2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;

namespace AppControlManager.CustomUIElements
{
/// <summary>
/// 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.
/// </summary>
internal sealed partial class MenuFlyoutV2 : MenuFlyout
{
/// <summary>
/// Initializes a new instance of the <see cref="MenuFlyoutV2"/> class.
/// Subscribes to the Opened event to attach pointer event handlers to the menu items.
/// </summary>
internal MenuFlyoutV2()
{
// Attach the handler for the Opened event to initialize event listeners for pointer interactions on menu items
Opened += MenuFlyoutV2_Opened;
}

/// <summary>
/// Property to track whether the user's pointer is currently over any menu item in the flyout.
/// </summary>
internal bool IsPointerOver { get; set; }

/// <summary>
/// Event handler for when the flyout is opened.
/// Attaches PointerEntered and PointerExited event handlers to each item in the flyout.
/// </summary>
/// <param name="sender">The source of the event (the flyout itself).</param>
/// <param name="e">The event data.</param>
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;
}
}

/// <summary>
/// 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.
/// </summary>
/// <param name="sender">The menu item that the pointer entered.</param>
/// <param name="e">The event data for the pointer interaction.</param>
private void MenuItem_PointerEntered(object sender, PointerRoutedEventArgs e)
{
// Set IsPointerOver to true, indicating the pointer is inside the flyout
IsPointerOver = true;
}

/// <summary>
/// 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.
/// </summary>
/// <param name="sender">The menu item that the pointer exited.</param>
/// <param name="e">The event data for the pointer interaction.</param>
private void MenuItem_PointerExited(object sender, PointerRoutedEventArgs e)
{
// Set IsPointerOver to false, indicating the pointer has left the flyout
IsPointerOver = false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -44,7 +45,8 @@
</Button.Content>

<Button.Flyout>
<MenuFlyout>

<customUI:MenuFlyoutV2 Closing="MenuFlyout_Closing">

<ToggleMenuFlyoutItem Text="Base Policies" x:Name="IncludeBasePolicies" IsChecked="True">
<ToggleMenuFlyoutItem.Icon>
Expand All @@ -70,7 +72,7 @@
</ToggleMenuFlyoutItem.Icon>
</ToggleMenuFlyoutItem>

</MenuFlyout>
</customUI:MenuFlyoutV2>
</Button.Flyout>
</Button>

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,6 +13,7 @@

namespace AppControlManager.Pages
{

public sealed partial class ViewCurrentPolicies : Page
{
// To store the policies displayed on the DataGrid
Expand Down Expand Up @@ -559,5 +559,22 @@ private static string ConvertRowToText(CiPolicyInfo row)
}


#pragma warning disable CA1822

/// <summary>
/// Event handler to prevent the MenuFlyout to automatically close immediately after selecting a checkbox or any button in it
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void MenuFlyout_Closing(FlyoutBase sender, FlyoutBaseClosingEventArgs args)
{
if (sender is CustomUIElements.MenuFlyoutV2 { IsPointerOver: true })
{
args.Cancel = true;
}
}

#pragma warning restore CA1822

}
}
Loading