From 8a0ccea2731e2df48d105f9e5fea25e6f1361fb9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 22 Feb 2020 10:02:19 +0100 Subject: [PATCH] Add MenuItem.InputGestureText. --- src/Avalonia.Controls/MenuItem.cs | 51 +++++++++++++++++++++++ src/Avalonia.Themes.Default/MenuItem.xaml | 26 ++++++++---- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index e0baa5e679..ae36b5d830 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -13,6 +13,7 @@ using Avalonia.Data; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; +using Avalonia.VisualTree; namespace Avalonia.Controls { @@ -48,6 +49,12 @@ namespace Avalonia.Controls public static readonly StyledProperty IconProperty = AvaloniaProperty.Register(nameof(Icon)); + /// + /// Defines the property. + /// + public static readonly StyledProperty InputGestureTextProperty = + AvaloniaProperty.Register(nameof(InputGestureText)); + /// /// Defines the property. /// @@ -93,6 +100,7 @@ namespace Avalonia.Controls private ICommand _command; private bool _commandCanExecute = true; private Popup _popup; + private IDisposable _gridHack; /// /// Initializes static members of the class. @@ -194,6 +202,19 @@ namespace Avalonia.Controls set { SetValue(IconProperty, value); } } + /// + /// Gets or sets the input gesture that will be displayed in the menu item. + /// + /// + /// Setting this property does not cause the input gesture to be handled by the menu item, + /// it simply displays the gesture text in the menu. + /// + public object InputGestureText + { + get { return GetValue(InputGestureTextProperty); } + set { SetValue(InputGestureTextProperty, value); } + } + /// /// Gets or sets a value indicating whether the is currently selected. /// @@ -306,6 +327,36 @@ namespace Avalonia.Controls } } + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + + if (this.GetVisualParent() is IControl parent) + { + // HACK: This nasty but it's all WPF's fault. Grid uses an inherited attached + // property to store SharedSizeGroup state, except property inheritance is done + // down the logical tree. In this case, the control which is setting + // Grid.IsSharedSizeScope="True" is not in the logical tree. Instead of fixing + // the way Grid stores shared size state, the developers of WPF just created a + // binding of the internal state of the visual parent to the menu item. We don't + // have much choice but to do the same for now unless we want to refactor Grid, + // which I honestly am not brave enough to do right now. Here's the same hack in + // the WPF codebase: + // + // https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141 + _gridHack = Bind( + DefinitionBase.PrivateSharedSizeScopeProperty, + parent.GetBindingObservable(DefinitionBase.PrivateSharedSizeScopeProperty)); + } + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + _gridHack.Dispose(); + _gridHack = null; + } + /// /// Called when the is clicked. /// diff --git a/src/Avalonia.Themes.Default/MenuItem.xaml b/src/Avalonia.Themes.Default/MenuItem.xaml index 93989d3782..431adacb47 100644 --- a/src/Avalonia.Themes.Default/MenuItem.xaml +++ b/src/Avalonia.Themes.Default/MenuItem.xaml @@ -11,7 +11,14 @@ Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> - + + + + + + + + + + Grid.Column="4"/> + Margin="4 2" + Grid.IsSharedSizeScope="True"/> @@ -102,10 +113,11 @@ BorderThickness="{TemplateBinding BorderThickness}"> + Items="{TemplateBinding Items}" + ItemsPanel="{TemplateBinding ItemsPanel}" + ItemTemplate="{TemplateBinding ItemTemplate}" + Margin="2" + Grid.IsSharedSizeScope="True"/>