From a90a027b5347f1f9cc1e90343174b4e5476a00e7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 27 May 2015 01:17:00 +0200 Subject: [PATCH] Close menu when clicked outside. --- Perspex.Controls/Menu.cs | 30 ++++++++++++++++++++++++++++++ Perspex.Controls/MenuItem.cs | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Perspex.Controls/Menu.cs b/Perspex.Controls/Menu.cs index 79773ea7fd..19463ca1a0 100644 --- a/Perspex.Controls/Menu.cs +++ b/Perspex.Controls/Menu.cs @@ -6,14 +6,19 @@ namespace Perspex.Controls { + using System; using System.Linq; + using Perspex.Input; using Perspex.LogicalTree; + using Perspex.Rendering; public class Menu : ItemsControl, IMenu { private static readonly ItemsPanelTemplate DefaultPanel = new ItemsPanelTemplate(() => new StackPanel { Orientation = Orientation.Horizontal }); + private IDisposable subscription; + static Menu() { ItemsPanelProperty.OverrideDefaultValue(typeof(Menu), DefaultPanel); @@ -31,5 +36,30 @@ namespace Perspex.Controls } } } + + protected override void OnAttachedToVisualTree(IRenderRoot root) + { + base.OnAttachedToVisualTree(root); + + var r = root as IInputElement; + this.subscription = r.AddHandler( + InputElement.PointerPressedEvent, + this.RootPointerPressed, + Interactivity.RoutingStrategies.Tunnel); + } + + protected override void OnDetachedFromVisualTree(IRenderRoot oldRoot) + { + base.OnDetachedFromVisualTree(oldRoot); + this.subscription.Dispose(); + } + + private void RootPointerPressed(object sender, PointerPressEventArgs e) + { + foreach (var i in this.GetLogicalChildren().Cast()) + { + i.IsSubMenuOpen = false; + } + } } } diff --git a/Perspex.Controls/MenuItem.cs b/Perspex.Controls/MenuItem.cs index 3fabb086b0..66851159aa 100644 --- a/Perspex.Controls/MenuItem.cs +++ b/Perspex.Controls/MenuItem.cs @@ -6,10 +6,15 @@ namespace Perspex.Controls { + using System; + using System.Linq; + using System.Windows.Input; using Perspex.Controls.Primitives; using Perspex.Input; using Perspex.LogicalTree; - using System.Windows.Input; + using Perspex.Collections; + using Perspex.Rendering; + using Perspex.Controls.Templates; public class MenuItem : HeaderedItemsControl { @@ -25,6 +30,11 @@ namespace Perspex.Controls public static readonly PerspexProperty IsSubMenuOpenProperty = PerspexProperty.Register("IsSubMenuOpen"); + static MenuItem() + { + IsSubMenuOpenProperty.Changed.Subscribe(SubMenuOpenChanged); + } + public ICommand Command { get { return this.GetValue(CommandProperty); } @@ -64,5 +74,26 @@ namespace Perspex.Controls this.IsSubMenuOpen = !this.IsSubMenuOpen; } } + + private void OnSubMenuOpenChanged(bool open) + { + if (!open && this.Items != null) + { + foreach (var item in this.Items.Cast().OfType()) + { + item.IsSubMenuOpen = false; + } + } + } + + private static void SubMenuOpenChanged(PerspexPropertyChangedEventArgs e) + { + var sender = e.Sender as MenuItem; + + if (sender != null) + { + sender.OnSubMenuOpenChanged((bool)e.NewValue); + } + } } }