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>
|
/// <summary>
|
||||||
/// Represents a <see cref="MenuItem"/>.
|
/// Represents a <see cref="MenuItem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IMenuItem : IMenuElement
|
internal interface IMenuItem : IMenuElement
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.HasSubMenu"/>
|
||||||
/// Gets or sets a value that indicates whether the item has a submenu.
|
|
||||||
/// </summary>
|
|
||||||
bool HasSubMenu { get; }
|
bool HasSubMenu { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -17,21 +13,13 @@ namespace Avalonia.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsPointerOverSubMenu { get; }
|
bool IsPointerOverSubMenu { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.IsSubMenuOpen"/>
|
||||||
/// Gets or sets a value that indicates whether the submenu of the <see cref="MenuItem"/> is
|
|
||||||
/// open.
|
|
||||||
/// </summary>
|
|
||||||
bool IsSubMenuOpen { get; set; }
|
bool IsSubMenuOpen { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.StaysOpenOnClick"/>
|
||||||
/// 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>
|
|
||||||
bool StaysOpenOnClick { get; set; }
|
bool StaysOpenOnClick { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.IsTopLevel"/>
|
||||||
/// Gets a value that indicates whether the <see cref="MenuItem"/> is a top-level main menu item.
|
|
||||||
/// </summary>
|
|
||||||
bool IsTopLevel { get; }
|
bool IsTopLevel { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,20 +27,13 @@ namespace Avalonia.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
IMenuElement? Parent { get; }
|
IMenuElement? Parent { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.ToggleType"/>
|
||||||
/// Gets toggle type of the menu item.
|
|
||||||
/// </summary>
|
|
||||||
MenuItemToggleType ToggleType { get; }
|
MenuItemToggleType ToggleType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.GroupName"/>
|
||||||
/// Gets menu item group name when <see cref="ToggleType"/> is <see cref="MenuItemToggleType.Radio"/>.
|
|
||||||
/// </summary>
|
|
||||||
string? GroupName { get; }
|
string? GroupName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="MenuItem.IsChecked"/>
|
||||||
/// Gets or sets if menu item is checked when <see cref="ToggleType"/> is
|
|
||||||
/// <see cref="MenuItemToggleType.CheckBox"/> or <see cref="MenuItemToggleType.Radio"/>.
|
|
||||||
/// </summary>
|
|
||||||
bool IsChecked { get; set; }
|
bool IsChecked { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -288,6 +288,12 @@ namespace Avalonia.Controls
|
|||||||
set => SetValue(IsSubMenuOpenProperty, value);
|
set => SetValue(IsSubMenuOpenProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IMenuItem.IsSubMenuOpen
|
||||||
|
{
|
||||||
|
get => IsSubMenuOpen;
|
||||||
|
set => SetCurrentValue(IsSubMenuOpenProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
|
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
|
||||||
/// within should not close when this item is clicked.
|
/// within should not close when this item is clicked.
|
||||||
@@ -298,27 +304,46 @@ namespace Avalonia.Controls
|
|||||||
set => SetValue(StaysOpenOnClickProperty, value);
|
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
|
public MenuItemToggleType ToggleType
|
||||||
{
|
{
|
||||||
get => GetValue(ToggleTypeProperty);
|
get => GetValue(ToggleTypeProperty);
|
||||||
set => SetValue(ToggleTypeProperty, value);
|
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
|
public bool IsChecked
|
||||||
{
|
{
|
||||||
get => GetValue(IsCheckedProperty);
|
get => GetValue(IsCheckedProperty);
|
||||||
set => SetValue(IsCheckedProperty, value);
|
set => SetValue(IsCheckedProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IMenuItem.IsChecked
|
||||||
|
{
|
||||||
|
get => IsChecked;
|
||||||
|
set => SetCurrentValue(IsCheckedProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
bool IRadioButton.IsChecked
|
bool IRadioButton.IsChecked
|
||||||
{
|
{
|
||||||
get => IsChecked;
|
get => IsChecked;
|
||||||
set => SetCurrentValue(IsCheckedProperty, value);
|
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
|
public string? GroupName
|
||||||
{
|
{
|
||||||
get => GetValue(GroupNameProperty);
|
get => GetValue(GroupNameProperty);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Avalonia.Controls.Platform;
|
using Avalonia.Controls.Platform;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Data;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.UnitTests;
|
using Avalonia.UnitTests;
|
||||||
@@ -12,11 +15,11 @@ namespace Avalonia.Controls.UnitTests.Platform
|
|||||||
public class DefaultMenuInteractionHandlerTests : ScopedTestBase
|
public class DefaultMenuInteractionHandlerTests : ScopedTestBase
|
||||||
{
|
{
|
||||||
static PointerPressedEventArgs CreatePressed(object source) => new PointerPressedEventArgs(source,
|
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);
|
default);
|
||||||
|
|
||||||
static PointerReleasedEventArgs CreateReleased(object source) => new PointerReleasedEventArgs(source,
|
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),
|
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonReleased),
|
||||||
default, MouseButton.Left);
|
default, MouseButton.Left);
|
||||||
|
|
||||||
@@ -224,6 +227,63 @@ namespace Avalonia.Controls.UnitTests.Platform
|
|||||||
|
|
||||||
target.KeyDown(menu, e);
|
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
|
public class NonTopLevel : ScopedTestBase
|
||||||
|
|||||||
Reference in New Issue
Block a user