using System; using System.Windows.Input; using Avalonia.Input; 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 NativeMenu _menu; static NativeMenuItem() { MenuProperty.Changed.Subscribe(args => { var item = (NativeMenuItem)args.Sender; var value = (NativeMenu)args.NewValue; if (value.Parent != null && value.Parent != item) throw new InvalidOperationException("NativeMenu already has a parent"); value.Parent = item; }); } class CanExecuteChangedSubscriber : IWeakSubscriber { private readonly NativeMenuItem _parent; public CanExecuteChangedSubscriber(NativeMenuItem parent) { _parent = parent; } public void OnEvent(object sender, EventArgs e) { _parent.CanExecuteChanged(); } } private readonly CanExecuteChangedSubscriber _canExecuteChangedSubscriber; 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); public NativeMenu Menu { get => _menu; set { if (value.Parent != null && value.Parent != this) throw new InvalidOperationException("NativeMenu already has a parent"); SetAndRaise(MenuProperty, ref _menu, 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 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(null) ?? true; } public bool HasClickHandlers => Clicked != null; public ICommand Command { get => _command; set { if (_command != null) WeakSubscriptionManager.Unsubscribe(_command, nameof(ICommand.CanExecuteChanged), _canExecuteChangedSubscriber); SetAndRaise(CommandProperty, ref _command, value); if (_command != null) WeakSubscriptionManager.Subscribe(_command, nameof(ICommand.CanExecuteChanged), _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); } } public event EventHandler Clicked; void INativeMenuItemExporterEventsImplBridge.RaiseClicked() { Clicked?.Invoke(this, new EventArgs()); if (Command?.CanExecute(CommandParameter) == true) { Command.Execute(CommandParameter); } } } }