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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Avalonia.Automation;
|
using Avalonia.Automation;
|
||||||
@@ -341,7 +342,7 @@ namespace Avalonia.Controls
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IMenuElement? IMenuItem.Parent => Parent as IMenuElement;
|
IMenuElement? IMenuItem.Parent => Parent as IMenuElement;
|
||||||
|
|
||||||
protected override bool IsEnabledCore => base.IsEnabledCore && _commandCanExecute;
|
protected override bool IsEnabledCore => base.IsEnabled && (HasSubMenu || _commandCanExecute);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
bool IMenuElement.MoveSelection(NavigationDirection direction, bool wrap) => MoveSelection(direction, wrap);
|
bool IMenuElement.MoveSelection(NavigationDirection direction, bool wrap) => MoveSelection(direction, wrap);
|
||||||
@@ -710,6 +711,15 @@ namespace Avalonia.Controls
|
|||||||
{
|
{
|
||||||
GroupNameChanged(change);
|
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>
|
/// <summary>
|
||||||
/// Called when the <see cref="GroupName"/> property changes.
|
/// Called when the <see cref="GroupName"/> property changes.
|
||||||
|
|||||||
@@ -62,6 +62,45 @@ namespace Avalonia.Controls.UnitTests
|
|||||||
Assert.False(target.IsEffectivelyEnabled);
|
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]
|
[Fact]
|
||||||
public void MenuItem_Is_Disabled_When_Bound_Command_Is_Removed()
|
public void MenuItem_Is_Disabled_When_Bound_Command_Is_Removed()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user