using System; using System.Windows.Input; using Avalonia.Input; using Avalonia.Media.Imaging; using Avalonia.Metadata; using Avalonia.Utilities; namespace Avalonia.Controls { public class NativeMenuItem : NativeMenuItemBase, INativeMenuItemExporterEventsImplBridge { private string? _header; private KeyGesture? _gesture; private bool _isEnabled = true; private ICommand? _command; private bool _isChecked = false; private NativeMenuItemToggleType _toggleType; private IBitmap? _icon; private readonly CanExecuteChangedSubscriber _canExecuteChangedSubscriber; private NativeMenu? _menu; static NativeMenuItem() { MenuProperty.Changed.Subscribe(args => { var item = (NativeMenuItem)args.Sender; var value = args.NewValue.GetValueOrDefault()!; if (value.Parent != null && value.Parent != item) throw new InvalidOperationException("NativeMenu already has a parent"); value.Parent = item; }); } class CanExecuteChangedSubscriber : IWeakEventSubscriber { private readonly NativeMenuItem _parent; public CanExecuteChangedSubscriber(NativeMenuItem parent) { _parent = parent; } public void OnEvent(object? sender, WeakEvent ev, EventArgs e) { _parent.CanExecuteChanged(); } } public NativeMenuItem() { _canExecuteChangedSubscriber = new CanExecuteChangedSubscriber(this); } public NativeMenuItem(string header) : this() { Header = header; } public static readonly DirectProperty MenuProperty = AvaloniaProperty.RegisterDirect(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v); [Content] public NativeMenu? Menu { get => _menu; set { if (value != null && value.Parent != null && value.Parent != this) throw new InvalidOperationException("NativeMenu already has a parent"); SetAndRaise(MenuProperty, ref _menu, value); } } public static readonly DirectProperty IconProperty = AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v); public IBitmap? Icon { get => _icon; set => SetAndRaise(IconProperty, ref _icon, value); } public static readonly DirectProperty HeaderProperty = AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v); public string? Header { get => _header; set => SetAndRaise(HeaderProperty, ref _header, value); } public static readonly DirectProperty GestureProperty = AvaloniaProperty.RegisterDirect(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v); public KeyGesture? Gesture { get => _gesture; set => SetAndRaise(GestureProperty, ref _gesture, value); } public static readonly DirectProperty IsCheckedProperty = AvaloniaProperty.RegisterDirect( nameof(IsChecked), o => o.IsChecked, (o, v) => o.IsChecked = v); public bool IsChecked { get => _isChecked; set => SetAndRaise(IsCheckedProperty, ref _isChecked, value); } public static readonly DirectProperty ToggleTypeProperty = AvaloniaProperty.RegisterDirect( nameof(ToggleType), o => o.ToggleType, (o, v) => o.ToggleType = v); public NativeMenuItemToggleType ToggleType { get => _toggleType; set => SetAndRaise(ToggleTypeProperty, ref _toggleType, value); } public static readonly DirectProperty CommandProperty = Button.CommandProperty.AddOwner( menuItem => menuItem.Command, (menuItem, command) => menuItem.Command = command, enableDataValidation: true); /// /// Defines the property. /// public static readonly StyledProperty CommandParameterProperty = Button.CommandParameterProperty.AddOwner(); public static readonly DirectProperty IsEnabledProperty = AvaloniaProperty.RegisterDirect(nameof(IsEnabled), o => o.IsEnabled, (o, v) => o.IsEnabled = v, true); public bool IsEnabled { get => _isEnabled; set => SetAndRaise(IsEnabledProperty, ref _isEnabled, value); } void CanExecuteChanged() { IsEnabled = _command?.CanExecute(CommandParameter) ?? true; } public bool HasClickHandlers => Click != null; public ICommand? Command { get => _command; set { if (_command != null) WeakEvents.CommandCanExecuteChanged.Unsubscribe(_command, _canExecuteChangedSubscriber); SetAndRaise(CommandProperty, ref _command, value); if (_command != null) WeakEvents.CommandCanExecuteChanged.Subscribe(_command, _canExecuteChangedSubscriber); CanExecuteChanged(); } } /// /// Gets or sets the parameter to pass to the property of a /// . /// public object? CommandParameter { get { return GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } /// /// Occurs when a is clicked. /// public event EventHandler? Click; [Obsolete("Use Click event.")] public event EventHandler Clicked { add => Click += value; remove => Click -= value; } void INativeMenuItemExporterEventsImplBridge.RaiseClicked() { Click?.Invoke(this, new EventArgs()); if (Command?.CanExecute(CommandParameter) == true) { Command.Execute(CommandParameter); } } } public enum NativeMenuItemToggleType { None, CheckBox, Radio } }