Browse Source

Added implementation of ContextMenus.

pull/405/head
danwalmsley 10 years ago
parent
commit
f32f293f30
  1. 16
      samples/XamlTestApplicationPcl/Views/MainWindow.paml
  2. 154
      src/Perspex.Controls/ContextMenu.cs
  3. 16
      src/Perspex.Controls/Control.cs
  4. 4
      src/Perspex.Themes.Default/ContextMenu.paml

16
samples/XamlTestApplicationPcl/Views/MainWindow.paml

@ -38,8 +38,20 @@
</TabItem>
<TabItem Header="Text">
<StackPanel Margin="10" Gap="4">
<TextBlock Text="TextBlock" FontWeight="Medium" FontSize="20" Foreground="#212121">
<ContextMenu.Menu></ContextMenu.Menu>
<TextBlock Text="TextBlock with ContextMenu" FontWeight="Medium" FontSize="20" Foreground="#212121">
<ContextMenu.ContextMenu>
<ContextMenu>
<MenuItem Header="Testing 1" />
<MenuItem Header="Testing 2" />
<MenuItem Header="Testing 3" />
<MenuItem Header="Testing 4">
<MenuItem Header="SubItem 1" />
<MenuItem Header="SubItem 2" />
<MenuItem Header="SubItem 3" />
<MenuItem Header="SubItem 4" />
</MenuItem>
</ContextMenu>
</ContextMenu.ContextMenu>
</TextBlock>
<TextBlock Text="A control for displaying text."
FontSize="13"

154
src/Perspex.Controls/ContextMenu.cs

@ -1,20 +1,162 @@
namespace Perspex.Controls
{
using Input;
using Interactivity;
using LogicalTree;
using Primitives;
using System;
using System.Reactive.Linq;
public class ContextMenu : SelectingItemsControl
{
public static readonly AttachedProperty<ContextMenu> MenuProperty =
PerspexProperty.RegisterAttached<ContextMenu, TextBlock, ContextMenu>("Menu");
private bool _isOpen;
public static ContextMenu GetMenu(TextBlock element)
/// <summary>
/// Defines the ContextMenu.Menu attached property.
/// </summary>
//public static readonly AttachedProperty<object> ContextMenuProperty =
// PerspexProperty.RegisterAttached<ContextMenu, Control, object>("Menu");
/// <summary>
/// The popup window used to display the active context menu.
/// </summary>
private static PopupRoot s_popup;
/// <summary>
/// The control that the currently visible context menu is attached to.
/// </summary>
private static Control s_current;
/// <summary>
/// Initializes static members of the <see cref="ToolTip"/> class.
/// </summary>
static ContextMenu()
{
ContextMenuProperty.Changed.Subscribe(ContextMenuChanged);
MenuItem.ClickEvent.AddClassHandler<ContextMenu>(x => x.OnContextMenuClick);
}
/// <summary>
/// Gets the value of the ToolTip.Tip attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <returns>
/// The content to be displayed in the control's tooltip.
/// </returns>
public static object GetContextMenu(Control element)
{
return element.GetValue(ContextMenuProperty);
}
/// <summary>
/// Sets the value of the ToolTip.Tip attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <param name="value">The content to be displayed in the control's tooltip.</param>
public static void SetContextMenu(Control element, object value)
{
element.SetValue(ContextMenuProperty, value);
}
/// <summary>
/// called when the <see cref="ContextMenuProperty"/> property changes on a control.
/// </summary>
/// <param name="e">The event args.</param>
private static void ContextMenuChanged(PerspexPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (e.OldValue != null)
{
control.PointerReleased -= ControlPointerReleased;
}
if (e.NewValue != null)
{
control.PointerReleased += ControlPointerReleased;
}
}
/// <summary>
/// Called when a submenu is clicked somewhere in the menu.
/// </summary>
/// <param name="e">The event args.</param>
private void OnContextMenuClick(RoutedEventArgs e)
{
return element.GetValue(MenuProperty);
Hide();
FocusManager.Instance.Focus(null);
e.Handled = true;
}
public static void SetMenu(TextBlock element, ContextMenu value)
/// <summary>
/// Closes the menu.
/// </summary>
public void Hide()
{
element.SetValue(MenuProperty, value);
foreach (MenuItem i in this.GetLogicalChildren())
{
i.IsSubMenuOpen = false;
}
if (s_popup != null && s_popup.IsVisible)
{
s_popup.Hide();
}
SelectedIndex = -1;
_isOpen = false;
}
/// <summary>
/// Shows a tooltip for the specified control.
/// </summary>
/// <param name="control">The control.</param>
private static void Show(Control control)
{
if (control != null)
{
if (s_popup == null)
{
s_popup = new PopupRoot
{
Content = new ToolTip(),
};
((ISetLogicalParent)s_popup).SetParent(control);
}
var cp = MouseDevice.Instance?.GetPosition(control);
var position = control.PointToScreen(cp ?? new Point(0, 0));
((ToolTip)s_popup.Content).Content = GetContextMenu(control);
s_popup.Position = position;
s_popup.Show();
s_current = control;
control.ContextMenu._isOpen = true;
}
}
private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e)
{
var control = (Control)sender;
if (e.MouseButton == MouseButton.Right)
{
if(control.ContextMenu._isOpen)
{
control.ContextMenu.Hide();
}
Show(control);
}
else
{
control.ContextMenu.Hide();
}
}
}
}

16
src/Perspex.Controls/Control.cs

@ -65,6 +65,13 @@ namespace Perspex.Controls
public static readonly StyledProperty<ITemplatedControl> TemplatedParentProperty =
PerspexProperty.Register<Control, ITemplatedControl>(nameof(TemplatedParent), inherits: true);
/// <summary>
/// Defines the <see cref="ContextMenu"/> property.
/// </summary>
public static readonly StyledProperty<ContextMenu> ContextMenuProperty =
PerspexProperty.Register<Control, ContextMenu>(nameof(ContextMenu));
/// <summary>
/// Event raised when an element wishes to be scrolled into view.
/// </summary>
@ -204,6 +211,15 @@ namespace Perspex.Controls
/// </summary>
public IControl Parent => _parent;
/// <summary>
/// Gets or sets a context menu to the control.
/// </summary>
public ContextMenu ContextMenu
{
get { return GetValue(ContextMenuProperty); }
set { SetValue(ContextMenuProperty, value); }
}
/// <summary>
/// Gets or sets a user-defined object attached to the control.
/// </summary>

4
src/Perspex.Themes.Default/ContextMenu.paml

@ -5,8 +5,8 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ItemsPresenter Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
<ItemsPresenter Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"
KeyboardNavigation.TabNavigation="Continue"/>
</Border>

Loading…
Cancel
Save