Browse Source

Correctly handle clicks outside Popups.

Set e.Handled = true on click outside Popup which removes the need for
the _closing stuff in DropDown.
pull/390/head
Steven Kirk 10 years ago
parent
commit
2c9e1f8f7c
  1. 20
      src/Perspex.Controls/DropDown.cs
  2. 37
      src/Perspex.Controls/Primitives/Popup.cs

20
src/Perspex.Controls/DropDown.cs

@ -2,11 +2,9 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using Perspex.Controls.Generators;
using Perspex.Controls.Primitives;
using Perspex.Controls.Shapes;
using Perspex.Controls.Templates;
using Perspex.Input;
using Perspex.Layout;
using Perspex.Media;
@ -14,6 +12,10 @@ using Perspex.VisualTree;
namespace Perspex.Controls
{
/// <summary>
/// A drop-down list control.
/// </summary>
public class DropDown : SelectingItemsControl, IContentControl
{
public static readonly PerspexProperty<object> ContentProperty =
@ -36,7 +38,6 @@ namespace Perspex.Controls
private bool _isDropDownOpen;
private Popup _popup;
private bool _closing;
static DropDown()
{
@ -73,7 +74,7 @@ namespace Perspex.Controls
set { SetAndRaise(IsDropDownOpenProperty, ref _isDropDownOpen, value); }
}
public object SelectionBoxItem
protected object SelectionBoxItem
{
get { return GetValue(SelectionBoxItemProperty); }
set { SetValue(SelectionBoxItemProperty, value); }
@ -112,18 +113,17 @@ namespace Perspex.Controls
protected override void OnPointerPressed(PointerPressEventArgs e)
{
if (!IsDropDownOpen && !_closing && ((IVisual)e.Source).GetVisualRoot() != typeof(PopupRoot))
if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() != typeof(PopupRoot))
{
IsDropDownOpen = true;
e.Handled = true;
}
_closing = false;
if (!e.Handled)
{
if (UpdateSelectionFromEventSource(e.Source))
{
_popup?.Close();
e.Handled = true;
}
}
@ -140,7 +140,6 @@ namespace Perspex.Controls
_popup = e.NameScope.Get<Popup>("PART_Popup");
_popup.Opened += PopupOpened;
_popup.Closed += PopupClosed;
}
private void PopupOpened(object sender, EventArgs e)
@ -154,11 +153,6 @@ namespace Perspex.Controls
}
}
private void PopupClosed(object sender, EventArgs e)
{
_closing = true;
}
private void SelectedItemChanged(PerspexPropertyChangedEventArgs e)
{
UpdateSelectionBoxItem(e.NewValue);

37
src/Perspex.Controls/Primitives/Popup.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Perspex.Input;
using Perspex.Interactivity;
using Perspex.Metadata;
using Perspex.Rendering;
@ -171,12 +172,11 @@ namespace Perspex.Controls.Primitives
}
_popupRoot.Position = GetPosition();
_popupRoot.AddHandler(PointerPressedEvent, MaybeClose, RoutingStrategies.Bubble, true);
if (_topLevel != null)
{
_topLevel.Deactivated += MaybeClose;
_topLevel.AddHandler(PointerPressedEvent, MaybeClose, RoutingStrategies.Tunnel);
_topLevel.Deactivated += TopLevelDeactivated;
_topLevel.AddHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel);
}
PopupRootCreated?.Invoke(this, EventArgs.Empty);
@ -193,9 +193,8 @@ namespace Perspex.Controls.Primitives
{
if (_popupRoot != null)
{
_popupRoot.PointerPressed -= MaybeClose;
_topLevel.RemoveHandler(PointerPressedEvent, MaybeClose);
_topLevel.Deactivated -= MaybeClose;
_topLevel.RemoveHandler(PointerPressedEvent, PointerPressedOutside);
_topLevel.Deactivated -= TopLevelDeactivated;
_popupRoot.Hide();
}
@ -292,23 +291,23 @@ namespace Perspex.Controls.Primitives
}
}
/// <summary>
/// Conditionally closes the popup in response to an event, based on the value of the
/// <see cref="StaysOpen"/> property.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void MaybeClose(object sender, EventArgs e)
private void PointerPressedOutside(object sender, PointerPressEventArgs e)
{
var routed = e as RoutedEventArgs;
var outside = true;
if (routed != null)
if (!StaysOpen)
{
outside = ((IVisual)routed.Source).GetVisualRoot() != this.PopupRoot;
var root = ((IVisual)e.Source).GetVisualRoot();
if (root != this.PopupRoot)
{
Close();
e.Handled = true;
}
}
}
if (outside && !StaysOpen)
private void TopLevelDeactivated(object sender, EventArgs e)
{
if (!StaysOpen)
{
Close();
}

Loading…
Cancel
Save