diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index 78dc994df7..13f00bdc87 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -7,11 +7,20 @@ namespace Avalonia.Controls
using System;
using System.Reactive.Linq;
using System.Linq;
+ using System.ComponentModel;
+
public class ContextMenu : SelectingItemsControl
{
private bool _isOpen;
private Popup _popup;
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty IsOpenProperty =
+ AvaloniaProperty.RegisterDirect(nameof(IsOpen), o => o.IsOpen);
+
+
///
/// Initializes static members of the class.
///
@@ -22,6 +31,26 @@ namespace Avalonia.Controls
MenuItem.ClickEvent.AddClassHandler(x => x.OnContextMenuClick, handledEventsToo: true);
}
+ ///
+ /// Gets a value indicating whether the popup is open
+ ///
+ public bool IsOpen => _isOpen;
+
+ ///
+ /// Occurs when the value of the
+ ///
+ /// property is changing from false to true.
+ ///
+ public event CancelEventHandler ContextMenuOpening;
+
+ ///
+ /// Occurs when the value of the
+ ///
+ /// property is changing from true to false.
+ ///
+ public event CancelEventHandler ContextMenuClosing;
+
+
///
/// Called when the property changes on a control.
///
@@ -59,12 +88,12 @@ namespace Avalonia.Controls
{
if (_popup != null && _popup.IsVisible)
{
- _popup.Close();
+ _popup.IsOpen = false;
}
SelectedIndex = -1;
- _isOpen = false;
+ SetAndRaise(IsOpenProperty, ref _isOpen, false);
}
///
@@ -89,11 +118,11 @@ namespace Avalonia.Controls
}
((ISetLogicalParent)_popup).SetParent(control);
- _popup.Child = control.ContextMenu;
+ _popup.Child = this;
- _popup.Open();
+ _popup.IsOpen = true;
- control.ContextMenu._isOpen = true;
+ SetAndRaise(IsOpenProperty, ref _isOpen, true);
}
}
@@ -118,21 +147,37 @@ namespace Avalonia.Controls
var control = (Control)sender;
var contextMenu = control.ContextMenu;
- if (e.MouseButton == MouseButton.Right)
+ if (control.ContextMenu._isOpen)
{
- if (control.ContextMenu._isOpen)
- {
- control.ContextMenu.Hide();
- }
+ if (contextMenu.CancelClosing())
+ return;
- contextMenu.Show(control);
+ control.ContextMenu.Hide();
e.Handled = true;
}
- else if (contextMenu._isOpen)
+
+ if (e.MouseButton == MouseButton.Right)
{
- control.ContextMenu.Hide();
+ if (contextMenu.CancelOpening())
+ return;
+
+ contextMenu.Show(control);
e.Handled = true;
}
}
+
+ private bool CancelClosing()
+ {
+ var eventArgs = new CancelEventArgs();
+ ContextMenuClosing?.Invoke(this, eventArgs);
+ return eventArgs.Cancel;
+ }
+
+ private bool CancelOpening()
+ {
+ var eventArgs = new CancelEventArgs();
+ ContextMenuOpening?.Invoke(this, eventArgs);
+ return eventArgs.Cancel;
+ }
}
}
diff --git a/src/Avalonia.Controls/Primitives/ToggleButton.cs b/src/Avalonia.Controls/Primitives/ToggleButton.cs
index dc9b70ab8c..1d2e2f2100 100644
--- a/src/Avalonia.Controls/Primitives/ToggleButton.cs
+++ b/src/Avalonia.Controls/Primitives/ToggleButton.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Controls.Primitives
nameof(IsChecked),
o => o.IsChecked,
(o, v) => o.IsChecked = v,
- unsetValue: false,
+ unsetValue: null,
defaultBindingMode: BindingMode.TwoWay);
public static readonly StyledProperty IsThreeStateProperty =
diff --git a/src/Avalonia.Themes.Default/MenuItem.xaml b/src/Avalonia.Themes.Default/MenuItem.xaml
index 47b4528f88..53965db016 100644
--- a/src/Avalonia.Themes.Default/MenuItem.xaml
+++ b/src/Avalonia.Themes.Default/MenuItem.xaml
@@ -122,6 +122,11 @@
+
+