Fix MenuItem enabled state in the presence of sub-items. (#18679)
* Add unit test for sub menu item testing * Parent menu items should not be disabled on command binding failure. If a menu has a failed `Command` binding, but also has sub-menu items, then it should not be disabled. --------- Co-authored-by: Anastassia Pellja <anyka545@gmail.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using Avalonia.Automation;
|
||||
@@ -341,7 +342,7 @@ namespace Avalonia.Controls
|
||||
/// <inheritdoc/>
|
||||
IMenuElement? IMenuItem.Parent => Parent as IMenuElement;
|
||||
|
||||
protected override bool IsEnabledCore => base.IsEnabledCore && _commandCanExecute;
|
||||
protected override bool IsEnabledCore => base.IsEnabled && (HasSubMenu || _commandCanExecute);
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool IMenuElement.MoveSelection(NavigationDirection direction, bool wrap) => MoveSelection(direction, wrap);
|
||||
@@ -710,6 +711,15 @@ namespace Avalonia.Controls
|
||||
{
|
||||
GroupNameChanged(change);
|
||||
}
|
||||
else if (change.Property == ItemCountProperty)
|
||||
{
|
||||
// A menu item with no sub-menu is effectively disabled if its command binding
|
||||
// failed: this means that the effectively enabled state depends on whether the
|
||||
// number of items in the menu is 0 or not.
|
||||
var (o, n) = change.GetOldAndNewValue<int>();
|
||||
if (o == 0 || n == 0)
|
||||
UpdateIsEffectivelyEnabled();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when the <see cref="GroupName"/> property changes.
|
||||
|
||||
@@ -62,6 +62,45 @@ namespace Avalonia.Controls.UnitTests
|
||||
Assert.False(target.IsEffectivelyEnabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MenuItem_With_Styled_Command_Binding_Should_Be_Enabled_With_Child_Missing_Command()
|
||||
{
|
||||
using var app = Application();
|
||||
|
||||
var viewModel = new MenuViewModel("Parent")
|
||||
{
|
||||
Children = [new MenuViewModel("Child")]
|
||||
};
|
||||
|
||||
var contextMenu = new ContextMenu
|
||||
{
|
||||
ItemsSource = new[] { viewModel },
|
||||
Styles =
|
||||
{
|
||||
new Style(x => x.OfType<MenuItem>())
|
||||
{
|
||||
Setters =
|
||||
{
|
||||
new Setter(MenuItem.HeaderProperty, new Binding("Header")),
|
||||
new Setter(MenuItem.ItemsSourceProperty, new Binding("Children")),
|
||||
new Setter(MenuItem.CommandProperty, new Binding("Command"))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var window = new Window { ContextMenu = contextMenu };
|
||||
window.Show();
|
||||
contextMenu.Open();
|
||||
|
||||
var parentMenuItem = Assert.IsType<MenuItem>(contextMenu.ContainerFromIndex(0));
|
||||
|
||||
Assert.Same(parentMenuItem.DataContext, viewModel);
|
||||
Assert.Same(parentMenuItem.ItemsSource, viewModel.Children);
|
||||
Assert.True(parentMenuItem.IsEnabled);
|
||||
Assert.True(parentMenuItem.IsEffectivelyEnabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MenuItem_Is_Disabled_When_Bound_Command_Is_Removed()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user