Browse Source

Tweak the MenuItem Grid hack.

To try and fix menu layout in the fluent theme.
pull/4448/head
Steven Kirk 6 years ago
parent
commit
db67fa2cf6
  1. 59
      src/Avalonia.Controls/MenuItem.cs

59
src/Avalonia.Controls/MenuItem.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Input;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Mixins;
@ -97,7 +98,6 @@ namespace Avalonia.Controls
private ICommand _command;
private bool _commandCanExecute = true;
private Popup _popup;
private IDisposable _gridHack;
/// <summary>
/// Initializes static members of the <see cref="MenuItem"/> class.
@ -119,6 +119,32 @@ namespace Avalonia.Controls
public MenuItem()
{
// 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
//
// In addition to the hack from WPF, we also make sure to return null when we have
// no parent. If we don't do this, inheritance falls back to the logical tree,
// causing the shared size scope in the parent MenuItem to be used, breaking
// menu layout.
var parentSharedSizeScope = this.GetObservable(VisualParentProperty)
.SelectMany(x =>
{
var parent = x as Control;
return parent?.GetObservable(DefinitionBase.PrivateSharedSizeScopeProperty) ??
Observable.Return<DefinitionBase.SharedSizeScope>(null);
});
this.Bind(DefinitionBase.PrivateSharedSizeScopeProperty, parentSharedSizeScope);
}
/// <summary>
@ -325,37 +351,6 @@ 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;
}
/// <summary>
/// Called when the <see cref="MenuItem"/> is clicked.
/// </summary>

Loading…
Cancel
Save