Browse Source

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
pull/20687/head
Tom Edwards 1 month ago
committed by GitHub
parent
commit
f4b5dc95b7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 35
      src/Avalonia.Controls/IMenuItem.cs
  2. 31
      src/Avalonia.Controls/MenuItem.cs
  3. 60
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

35
src/Avalonia.Controls/IMenuItem.cs

@ -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>

31
src/Avalonia.Controls/MenuItem.cs

@ -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);

60
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@ -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;
@ -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

Loading…
Cancel
Save