Use SetCurrentValue for all IMenuItem properties (#20682)
* Add IMenuItem binding tests * Use SetCurrentValue for all IMenuItem properties Fix XMLDoc comments for MenuItem being inherited from an internal type
This commit is contained in:
@@ -1,15 +1,11 @@
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Avalonia.Controls
|
||||
namespace Avalonia.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="MenuItem"/>.
|
||||
/// </summary>
|
||||
internal interface IMenuItem : IMenuElement
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the item has a submenu.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.HasSubMenu"/>
|
||||
bool HasSubMenu { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -17,21 +13,13 @@ namespace Avalonia.Controls
|
||||
/// </summary>
|
||||
bool IsPointerOverSubMenu { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the submenu of the <see cref="MenuItem"/> is
|
||||
/// open.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.IsSubMenuOpen"/>
|
||||
bool IsSubMenuOpen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
|
||||
/// within should not close when this item is clicked.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.StaysOpenOnClick"/>
|
||||
bool StaysOpenOnClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the <see cref="MenuItem"/> is a top-level main menu item.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.IsTopLevel"/>
|
||||
bool IsTopLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -39,20 +27,13 @@ namespace Avalonia.Controls
|
||||
/// </summary>
|
||||
IMenuElement? Parent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets toggle type of the menu item.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.ToggleType"/>
|
||||
MenuItemToggleType ToggleType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets menu item group name when <see cref="ToggleType"/> is <see cref="MenuItemToggleType.Radio"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.GroupName"/>
|
||||
string? GroupName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if menu item is checked when <see cref="ToggleType"/> is
|
||||
/// <see cref="MenuItemToggleType.CheckBox"/> or <see cref="MenuItemToggleType.Radio"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="MenuItem.IsChecked"/>
|
||||
bool IsChecked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -288,6 +288,12 @@ namespace Avalonia.Controls
|
||||
set => SetValue(IsSubMenuOpenProperty, value);
|
||||
}
|
||||
|
||||
bool IMenuItem.IsSubMenuOpen
|
||||
{
|
||||
get => IsSubMenuOpen;
|
||||
set => SetCurrentValue(IsSubMenuOpenProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
|
||||
/// within should not close when this item is clicked.
|
||||
@@ -298,27 +304,46 @@ namespace Avalonia.Controls
|
||||
set => SetValue(StaysOpenOnClickProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMenuItem.ToggleType" />
|
||||
bool IMenuItem.StaysOpenOnClick
|
||||
{
|
||||
get => StaysOpenOnClick;
|
||||
set => SetCurrentValue(StaysOpenOnClickProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets toggle type of the menu item.
|
||||
/// </summary>
|
||||
public MenuItemToggleType ToggleType
|
||||
{
|
||||
get => GetValue(ToggleTypeProperty);
|
||||
set => SetValue(ToggleTypeProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMenuItem.IsChecked"/>
|
||||
/// <summary>
|
||||
/// Gets or sets if menu item is checked when <see cref="ToggleType"/> is
|
||||
/// <see cref="MenuItemToggleType.CheckBox"/> or <see cref="MenuItemToggleType.Radio"/>.
|
||||
/// </summary>
|
||||
public bool IsChecked
|
||||
{
|
||||
get => GetValue(IsCheckedProperty);
|
||||
set => SetValue(IsCheckedProperty, value);
|
||||
}
|
||||
|
||||
bool IMenuItem.IsChecked
|
||||
{
|
||||
get => IsChecked;
|
||||
set => SetCurrentValue(IsCheckedProperty, value);
|
||||
}
|
||||
|
||||
bool IRadioButton.IsChecked
|
||||
{
|
||||
get => IsChecked;
|
||||
set => SetCurrentValue(IsCheckedProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMenuItem.GroupName"/>
|
||||
/// <summary>
|
||||
/// Gets menu item group name when <see cref="ToggleType"/> is <see cref="MenuItemToggleType.Radio"/>.
|
||||
/// </summary>
|
||||
public string? GroupName
|
||||
{
|
||||
get => GetValue(GroupNameProperty);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Avalonia.Controls.Platform;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.UnitTests;
|
||||
@@ -12,11 +15,11 @@ namespace Avalonia.Controls.UnitTests.Platform
|
||||
public class DefaultMenuInteractionHandlerTests : ScopedTestBase
|
||||
{
|
||||
static PointerPressedEventArgs CreatePressed(object source) => new PointerPressedEventArgs(source,
|
||||
new FakePointer(), (Visual)source, default,0, new PointerPointProperties (RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||
new FakePointer(), (Visual)source, default, 0, new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||
default);
|
||||
|
||||
static PointerReleasedEventArgs CreateReleased(object source) => new PointerReleasedEventArgs(source,
|
||||
new FakePointer(), (Visual)source, default,0,
|
||||
new FakePointer(), (Visual)source, default, 0,
|
||||
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonReleased),
|
||||
default, MouseButton.Left);
|
||||
|
||||
@@ -224,6 +227,63 @@ namespace Avalonia.Controls.UnitTests.Platform
|
||||
|
||||
target.KeyDown(menu, e);
|
||||
}
|
||||
|
||||
private class MenuItemVM : INotifyPropertyChanged
|
||||
{
|
||||
public bool IsChecked { get; set { field = value; OnPropertyChanged(); } }
|
||||
public bool IsSubMenuOpen { get; set { field = value; OnPropertyChanged(); } }
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new(propertyName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Doesnt_Replace_IsChecked_Binding()
|
||||
{
|
||||
var target = new DefaultMenuInteractionHandler(false);
|
||||
var menu = new Menu();
|
||||
var vm = new MenuItemVM();
|
||||
|
||||
var item = new MenuItem
|
||||
{
|
||||
DataContext = vm,
|
||||
[!MenuItem.IsCheckedProperty] = new Binding(nameof(MenuItemVM.IsChecked)) { Priority = BindingPriority.Style, Mode = BindingMode.TwoWay },
|
||||
ToggleType = MenuItemToggleType.CheckBox,
|
||||
};
|
||||
menu.Items.Add(item);
|
||||
|
||||
target.KeyDown(item, new KeyEventArgs { Key = Key.Enter, Source = menu });
|
||||
|
||||
Assert.True(item.IsChecked);
|
||||
|
||||
vm.IsChecked = false;
|
||||
|
||||
Assert.False(item.IsChecked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Doesnt_Replace_IsSubMenuOpen_Binding()
|
||||
{
|
||||
var target = new DefaultMenuInteractionHandler(false);
|
||||
var menu = new Menu();
|
||||
var vm = new MenuItemVM();
|
||||
|
||||
var item = new MenuItem
|
||||
{
|
||||
DataContext = vm,
|
||||
[!MenuItem.IsSubMenuOpenProperty] = new Binding(nameof(MenuItemVM.IsSubMenuOpen)) { Priority = BindingPriority.Style, Mode = BindingMode.TwoWay },
|
||||
Items = { new MenuItem() }
|
||||
};
|
||||
|
||||
target.KeyDown(item, new KeyEventArgs { Key = Key.Enter, Source = menu });
|
||||
|
||||
Assert.True(item.IsSubMenuOpen);
|
||||
|
||||
vm.IsSubMenuOpen = false;
|
||||
|
||||
Assert.False(item.IsSubMenuOpen);
|
||||
}
|
||||
}
|
||||
|
||||
public class NonTopLevel : ScopedTestBase
|
||||
|
||||
Reference in New Issue
Block a user