From 856ccb9640b469c63be15e8178542e796e7b6bac Mon Sep 17 00:00:00 2001 From: "DESKTOP-QJU4N0L\\mityh" Date: Sun, 9 Apr 2017 11:21:22 +1000 Subject: [PATCH 01/61] #981 adding ClassicMenu Control --- .../Microsoft.Toolkit.Uwp.SampleApp.csproj | 12 +- .../SamplePages/ClassicMenu/ClassicMenu.bind | 123 ++++++++++ .../SamplePages/ClassicMenu/ClassicMenu.png | Bin 0 -> 1247 bytes .../ClassicMenu/ClassicMenuPage.xaml | 41 ++++ .../ClassicMenu/ClassicMenuPage.xaml.cs | 74 ++++++ .../SamplePages/ClassicMenu/DialogCommand.cs | 26 +++ .../SamplePages/samples.json | 11 +- .../ClassicMenu/ClassicMenu.cs | 218 ++++++++++++++++++ .../ClassicMenu/ClassicMenu.xaml | 37 +++ .../ClassicMenu/ClassicMenuItem.cs | 79 +++++++ .../Microsoft.Toolkit.Uwp.UI.Controls.csproj | 7 + .../Themes/Generic.xaml | 1 + 12 files changed, 627 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.bind create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.png create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj index 12233d05f5c..cb7d6ceeab1 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj +++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj @@ -234,6 +234,7 @@ + @@ -382,6 +383,7 @@ + @@ -399,6 +401,10 @@ AdvancedCollectionViewPage.xaml + + ClassicMenuPage.xaml + + NetworkHelperPage.xaml @@ -408,7 +414,7 @@ ViewExtensionsPage.xaml - + CarouselPage.xaml @@ -638,6 +644,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + MSBuild:Compile Designer diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.bind new file mode 100644 index 00000000000..10bdf1364ca --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.bind @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect RowDefinition MinHeight="100" + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect + + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect + + + This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect + + + + + + + + + + + + + + + + + + diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenu.png new file mode 100644 index 0000000000000000000000000000000000000000..3ed298e71fd1e12d459001b2dbdbd95220708c80 GIT binary patch literal 1247 zcmV<51R(o~P)_~U0q#iX=!Y1Y;bUJa&mHZc6NDrd3t(!etv$1g@u`!nVOoKo12@QoSdDV zou8kdprD|kp`oIpqNAgurKP2&rlzN-r>Ll?si~=|s;aB2tE{Z7t*x!DuCA}IuduMN zv9YnTva++Yv$V9dwY9ajwzjvox45{txw*Nzy1Ki&yS%)-y}iA@zP`V|zreu2!NI}8 z!otJD!^FhI#l^+O#>U6T$H>UY$;rve%F4^j%gxQr&d$!y&(F}%(9zM+($dn@)YR40 z)z;S5*VotB*x1?G+1uOO+}zyV-QC~c-{Ilm;^N}tFVn0 z>+9?6?CkCB?b_PfZEbCml9JQY)92^s;Naly?(WRY%--JK&D-0V00003bW%=J09=`6 ztNmsG00Uo1L_t(|UhJ655r7~R#Dq2PiMIF|}j@)Fk@ zrXC=EK=z0&ZXi>vn^OZ3$jM^uoC3r-iHSSN895CQ=OiW`AZO&%L7bDAI6%;x{6H-B z1MvfScXb@U5?idC(ooj z?dR2?>S|`=p0xEH^OYaMhX2Tp)1qC zbX^MHYZS-`f?h#~yD$h~UDlo+L81qnm6}=&8-4%)>-n)i|0aQ7$21E(X;FWmS9aDEIlNskrg(*U_7tm?)Jm$CrY3DK8(+v-e}-{HaeD}Y((0NDZ^eqA6bE=fa+?W{mS ziw-n|K%}HN?JSnTZnBC9h?EtfoyAhvEmjZ*k&1$Jw^&9JM5^-Z(%WJQSrDnor$cXx zMHN7#4xa{1ERKndW#;6;3OKkxBo8|`c4-!FGB;Wc+}5%Y2mlzz6t>@A9sd9T002ov JPDHLkV1h}%e6#=n literal 0 HcmV?d00001 diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml new file mode 100644 index 00000000000..c86771679f3 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs new file mode 100644 index 00000000000..c0ff9a3cf5f --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class ClassicMenuPage : Page + { + public ClassicMenuPage() + { + this.InitializeComponent(); + //Loaded += ClassicMenuPage_Loaded; + } + + private void ClassicMenuPage_Loaded(object sender, RoutedEventArgs e) + { + //deep. + //deep.ContextFlyout.ShowAt(butttton); + //butttton.Flyout.ShowAt(butttton); + //butttton.Flyout.fl + //Flyout.ShowAttachedFlyout(butttton); + } + + private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e) + { + //// Create the message dialog and set its content + //var messageDialog = new MessageDialog("No internet connection has been found."); + + //// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers + //messageDialog.Commands.Add(new UICommand( + // "Try again", + // new UICommandInvokedHandler(this.CommandInvokedHandler))); + //messageDialog.Commands.Add(new UICommand( + // "Close", + // new UICommandInvokedHandler(this.CommandInvokedHandler))); + + //// Set the command that will be invoked by default + //messageDialog.DefaultCommandIndex = 0; + + //// Set the command to be invoked when escape is pressed + //messageDialog.CancelCommandIndex = 1; + + //// Show the message dialog + //await messageDialog.ShowAsync(); + + //var dialog = new MessageDialog("Your message here"); + //await dialog.ShowAsync(); + } + + private void CommandInvokedHandler(IUICommand command) + { + // Display message showing the label of the command that was invoked + //rootPage.NotifyUser("The '" + command.Label + "' command has been selected.", + // NotifyType.StatusMessage); + } + } +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs new file mode 100644 index 00000000000..d3c59a8fbd3 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.UI.Popups; + +namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ClassicMenu +{ + public class DialogCommand : ICommand + { + public bool CanExecute(object parameter) + { + return true; + } + + public async void Execute(object parameter) + { + var dialog = new MessageDialog("Your message here"); + await dialog.ShowAsync(); + } + + public event EventHandler CanExecuteChanged; + } +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json index af1b2eb04a6..0ab9411a2c5 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json @@ -3,7 +3,7 @@ "Name": "Controls", "Icon": "Icons/Foundation.png", "Samples": [ - { + { "Name": "Carousel", "Type": "CarouselPage", "About": "Presents items in a carousel control. It reacts to changes in the layout as well as the content so it can adapt to different form factors automatically.", @@ -212,6 +212,15 @@ "XamlCodeFile": "TextBoxRegex.bind", "Icon": "/SamplePages/TextBoxRegex/TextBoxRegex.png", "DocumentationUrl": "https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/dev/docs/controls/TextBoxRegex.md" + }, + { + "Name": "ClassicMenu", + "Type": "ClassicMenuPage", + "About": "", + "CodeUrl": "https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextBoxRegex", + "XamlCodeFile": "ClassicMenu.bind", + "Icon": "/SamplePages/ClassicMenu/ClassicMenu.png", + "DocumentationUrl": "https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/dev/docs/controls/TextBoxRegex.md" } ] }, diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs new file mode 100644 index 00000000000..d3956941f36 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.System; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + public class ClassicMenu : ItemsControl + { + private const string CtrlValue = "CTRL"; + private const string ShiftValue = "SHIFT"; + + // even if we have multiple menus in the same page we need only one cache because only one menu item will have certain short cut. + private static readonly Dictionary MenuItemInputGestureCache; + + public Orientation Orientation + { + get { return (Orientation)GetValue(OrientationProperty); } + set { SetValue(OrientationProperty, value); } + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty OrientationProperty = + DependencyProperty.Register( + "Orientation", + typeof(Orientation), + typeof(ClassicMenu), + new PropertyMetadata(Orientation.Horizontal)); + + static ClassicMenu() + { + MenuItemInputGestureCache = + new Dictionary(); + } + + public ClassicMenu() + { + DefaultStyleKey = typeof(ClassicMenu); + } + + /// + protected override void OnApplyTemplate() + { + Loaded -= ClassicMenu_Loaded; + Dispatcher.AcceleratorKeyActivated -= Dispatcher_AcceleratorKeyActivated; + + Loaded += ClassicMenu_Loaded; + Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated; + base.OnApplyTemplate(); + } + + private void ClassicMenu_Loaded(object sender, RoutedEventArgs e) + { + var wrapPanel = (WrapPanel.WrapPanel)ItemsPanelRoot; + wrapPanel.Orientation = Orientation; + } + + private static bool NavigateThrowMenuHeader(AcceleratorKeyEventArgs args, ClassicMenu menu, ClassicMenuItem menuItem, Orientation orientation) + { + if (orientation == Orientation.Horizontal) + { + if (args.VirtualKey == VirtualKey.Down) + { + menuItem.ShowMenu(); + return true; + } + + if (args.VirtualKey == VirtualKey.Left) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex > 0) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Left); + return true; + } + } + else if (args.VirtualKey == VirtualKey.Right) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex < menu.Items.Count - 1) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Right); + return true; + } + } + } + else + { + if (args.VirtualKey == VirtualKey.Right) + { + menuItem.ShowMenu(); + return true; + } + + if (args.VirtualKey == VirtualKey.Up) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex > 0) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Up); + return true; + } + } + else if (args.VirtualKey == VirtualKey.Down) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex < menu.Items.Count - 1) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Down); + return true; + } + } + } + + return false; + } + + public static readonly DependencyProperty InputGestureTextProperty = DependencyProperty.RegisterAttached("InputGestureText", typeof(string), typeof(MenuFlyoutItem), new PropertyMetadata(null, InputGestureTextChanged)); + + private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args) + { + if (args.VirtualKey == VirtualKey.Menu && !args.KeyStatus.WasKeyDown) + { + Focus(FocusState.Programmatic); + } + + var element = FocusManager.GetFocusedElement(); + var menuItem = element as ClassicMenuItem; + if (menuItem != null) + { + if (NavigateThrowMenuHeader(args, this, menuItem, Orientation)) + { + return; + } + } + + string gestureKey = MapInputToGestureKey(args); + + if (gestureKey == null) + { + return; + } + + if (MenuItemInputGestureCache.ContainsKey(gestureKey)) + { + var cachedMenuItem = MenuItemInputGestureCache[gestureKey]; + cachedMenuItem.Command?.Execute(cachedMenuItem.CommandParameter); + } + } + + private static string MapInputToGestureKey(AcceleratorKeyEventArgs args) + { + var isCtrlDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down); + var isShiftDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down); + + if (!isCtrlDown && !isShiftDown) + { + return null; + } + + StringBuilder gestureKeyBuilder = new StringBuilder(); + + if (isCtrlDown) + { + gestureKeyBuilder.Append(CtrlValue); + gestureKeyBuilder.Append("+"); + } + + if (isShiftDown) + { + gestureKeyBuilder.Append(ShiftValue); + gestureKeyBuilder.Append("+"); + } + + if (args.VirtualKey == VirtualKey.None) + { + gestureKeyBuilder.Remove(gestureKeyBuilder.Length - 1, 1); + } + else + { + gestureKeyBuilder.Append(args.VirtualKey); + } + + return gestureKeyBuilder.ToString(); + } + + private static void InputGestureTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + var inputGestureValue = e.NewValue as string; + if (string.IsNullOrEmpty(inputGestureValue) || MenuItemInputGestureCache.ContainsKey(inputGestureValue)) + { + return; + } + + var menuItem = (MenuFlyoutItem)obj; + MenuItemInputGestureCache.Add(inputGestureValue.ToUpper(), menuItem); + } + + public static string GetInputGestureText(MenuFlyoutItem obj) + { + return (string)obj.GetValue(InputGestureTextProperty); + } + + public static void SetInputGestureText(MenuFlyoutItem obj, string value) + { + obj.SetValue(InputGestureTextProperty, value); + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml new file mode 100644 index 00000000000..1aae15b2c01 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml @@ -0,0 +1,37 @@ + + + + + + + diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs new file mode 100644 index 00000000000..64c6e08cc35 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + public class ClassicMenuItem : ItemsControl + { + public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(nameof(Header), typeof(string), typeof(ClassicMenuItem), new PropertyMetadata(default(string))); + private Button _flyoutButton; + + /// + /// Gets or sets the title to appear in the title bar + /// + public string Header + { + get { return (string)GetValue(HeaderProperty); } + set { SetValue(HeaderProperty, value); } + } + + public ClassicMenuItem() + { + DefaultStyleKey = typeof(ClassicMenuItem); + } + + + public void ShowMenu() + { + _flyoutButton?.Flyout?.ShowAt(_flyoutButton); + } + + /// + protected override void OnApplyTemplate() + { + _flyoutButton = GetTemplateChild("FlyoutButton") as Button; + + if (_flyoutButton != null) + { + var menuFlyout = new MenuFlyout(); + menuFlyout.Placement = ParentMenu.Orientation == Orientation.Horizontal + ? FlyoutPlacementMode.Bottom + : FlyoutPlacementMode.Right; + if (Items != null) + { + foreach (var item in Items) + { + var menuItem = item as MenuFlyoutItemBase; + if (menuItem != null) + { + menuFlyout.Items?.Add(menuItem); + } + } + } + + _flyoutButton.Flyout = menuFlyout; + } + + + base.OnApplyTemplate(); + } + + protected override DependencyObject GetContainerForItemOverride() + { + return new MenuFlyoutItem(); + } + + protected override bool IsItemItsOwnContainerOverride(object item) + { + return item is MenuFlyoutItemBase; + } + + private ClassicMenu ParentMenu => this.FindAscendant(); + } +} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj index 36e76fa6f4e..e84810a7a8d 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj @@ -55,6 +55,8 @@ + + @@ -164,6 +166,11 @@ Designer XamlIntelliSenseFileGenerator + + MSBuild:Compile + Designer + PreserveNewest + MSBuild:Compile Designer diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Themes/Generic.xaml b/Microsoft.Toolkit.Uwp.UI.Controls/Themes/Generic.xaml index 24234da3773..1d41487f70d 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Themes/Generic.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Themes/Generic.xaml @@ -19,5 +19,6 @@ + From 2388c94aaa55d8f2807f8a9b60065d3fb7162c5b Mon Sep 17 00:00:00 2001 From: "DESKTOP-QJU4N0L\\mityh" Date: Sun, 9 Apr 2017 11:43:07 +1000 Subject: [PATCH 02/61] #981 creating parital classes --- .../ClassicMenu.InputGestureText.cs | 41 +++++ .../ClassicMenu/ClassicMenu.Logic.cs | 144 +++++++++++++++++ .../ClassicMenu/ClassicMenu.cs | 153 +----------------- .../ClassicMenu/ClassicMenuItem.cs | 3 +- .../Microsoft.Toolkit.Uwp.UI.Controls.csproj | 2 + 5 files changed, 189 insertions(+), 154 deletions(-) create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.InputGestureText.cs create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.InputGestureText.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.InputGestureText.cs new file mode 100644 index 00000000000..ffdcb5367f8 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.InputGestureText.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.System; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + public partial class ClassicMenu + { + public static readonly DependencyProperty InputGestureTextProperty = DependencyProperty.RegisterAttached("InputGestureText", typeof(string), typeof(MenuFlyoutItem), new PropertyMetadata(null, InputGestureTextChanged)); + + private static void InputGestureTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + var inputGestureValue = e.NewValue as string; + if (string.IsNullOrEmpty(inputGestureValue) || MenuItemInputGestureCache.ContainsKey(inputGestureValue)) + { + return; + } + + var menuItem = (MenuFlyoutItem)obj; + MenuItemInputGestureCache.Add(inputGestureValue.ToUpper(), menuItem); + } + + public static string GetInputGestureText(MenuFlyoutItem obj) + { + return (string)obj.GetValue(InputGestureTextProperty); + } + + public static void SetInputGestureText(MenuFlyoutItem obj, string value) + { + obj.SetValue(InputGestureTextProperty, value); + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs new file mode 100644 index 00000000000..fb0f91abc6b --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.System; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + public partial class ClassicMenu + { + private static bool NavigateThrowMenuHeader(AcceleratorKeyEventArgs args, ClassicMenu menu, ClassicMenuItem menuItem, Orientation orientation) + { + if (orientation == Orientation.Horizontal) + { + if (args.VirtualKey == VirtualKey.Down) + { + menuItem.ShowMenu(); + return true; + } + + if (args.VirtualKey == VirtualKey.Left) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex > 0) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Left); + return true; + } + } + else if (args.VirtualKey == VirtualKey.Right) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex < menu.Items.Count - 1) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Right); + return true; + } + } + } + else + { + if (args.VirtualKey == VirtualKey.Right) + { + menuItem.ShowMenu(); + return true; + } + + if (args.VirtualKey == VirtualKey.Up) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex > 0) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Up); + return true; + } + } + else if (args.VirtualKey == VirtualKey.Down) + { + var currentMenuItemIndex = menu.Items.IndexOf(menuItem); + if (currentMenuItemIndex < menu.Items.Count - 1) + { + FocusManager.TryMoveFocus(FocusNavigationDirection.Down); + return true; + } + } + } + + return false; + } + + private static string MapInputToGestureKey(AcceleratorKeyEventArgs args) + { + var isCtrlDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down); + var isShiftDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down); + + if (!isCtrlDown && !isShiftDown) + { + return null; + } + + StringBuilder gestureKeyBuilder = new StringBuilder(); + + if (isCtrlDown) + { + gestureKeyBuilder.Append(CtrlValue); + gestureKeyBuilder.Append("+"); + } + + if (isShiftDown) + { + gestureKeyBuilder.Append(ShiftValue); + gestureKeyBuilder.Append("+"); + } + + if (args.VirtualKey == VirtualKey.None) + { + gestureKeyBuilder.Remove(gestureKeyBuilder.Length - 1, 1); + } + else + { + gestureKeyBuilder.Append(args.VirtualKey); + } + + return gestureKeyBuilder.ToString(); + } + + private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args) + { + if (args.VirtualKey == VirtualKey.Menu && !args.KeyStatus.WasKeyDown) + { + Focus(FocusState.Programmatic); + } + + var element = FocusManager.GetFocusedElement(); + var menuItem = element as ClassicMenuItem; + if (menuItem != null) + { + if (NavigateThrowMenuHeader(args, this, menuItem, Orientation)) + { + return; + } + } + + string gestureKey = MapInputToGestureKey(args); + + if (gestureKey == null) + { + return; + } + + if (MenuItemInputGestureCache.ContainsKey(gestureKey)) + { + var cachedMenuItem = MenuItemInputGestureCache[gestureKey]; + cachedMenuItem.Command?.Execute(cachedMenuItem.CommandParameter); + } + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs index d3956941f36..f2287c14b2f 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs @@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls { - public class ClassicMenu : ItemsControl + public partial class ClassicMenu : ItemsControl { private const string CtrlValue = "CTRL"; private const string ShiftValue = "SHIFT"; @@ -63,156 +63,5 @@ private void ClassicMenu_Loaded(object sender, RoutedEventArgs e) var wrapPanel = (WrapPanel.WrapPanel)ItemsPanelRoot; wrapPanel.Orientation = Orientation; } - - private static bool NavigateThrowMenuHeader(AcceleratorKeyEventArgs args, ClassicMenu menu, ClassicMenuItem menuItem, Orientation orientation) - { - if (orientation == Orientation.Horizontal) - { - if (args.VirtualKey == VirtualKey.Down) - { - menuItem.ShowMenu(); - return true; - } - - if (args.VirtualKey == VirtualKey.Left) - { - var currentMenuItemIndex = menu.Items.IndexOf(menuItem); - if (currentMenuItemIndex > 0) - { - FocusManager.TryMoveFocus(FocusNavigationDirection.Left); - return true; - } - } - else if (args.VirtualKey == VirtualKey.Right) - { - var currentMenuItemIndex = menu.Items.IndexOf(menuItem); - if (currentMenuItemIndex < menu.Items.Count - 1) - { - FocusManager.TryMoveFocus(FocusNavigationDirection.Right); - return true; - } - } - } - else - { - if (args.VirtualKey == VirtualKey.Right) - { - menuItem.ShowMenu(); - return true; - } - - if (args.VirtualKey == VirtualKey.Up) - { - var currentMenuItemIndex = menu.Items.IndexOf(menuItem); - if (currentMenuItemIndex > 0) - { - FocusManager.TryMoveFocus(FocusNavigationDirection.Up); - return true; - } - } - else if (args.VirtualKey == VirtualKey.Down) - { - var currentMenuItemIndex = menu.Items.IndexOf(menuItem); - if (currentMenuItemIndex < menu.Items.Count - 1) - { - FocusManager.TryMoveFocus(FocusNavigationDirection.Down); - return true; - } - } - } - - return false; - } - - public static readonly DependencyProperty InputGestureTextProperty = DependencyProperty.RegisterAttached("InputGestureText", typeof(string), typeof(MenuFlyoutItem), new PropertyMetadata(null, InputGestureTextChanged)); - - private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args) - { - if (args.VirtualKey == VirtualKey.Menu && !args.KeyStatus.WasKeyDown) - { - Focus(FocusState.Programmatic); - } - - var element = FocusManager.GetFocusedElement(); - var menuItem = element as ClassicMenuItem; - if (menuItem != null) - { - if (NavigateThrowMenuHeader(args, this, menuItem, Orientation)) - { - return; - } - } - - string gestureKey = MapInputToGestureKey(args); - - if (gestureKey == null) - { - return; - } - - if (MenuItemInputGestureCache.ContainsKey(gestureKey)) - { - var cachedMenuItem = MenuItemInputGestureCache[gestureKey]; - cachedMenuItem.Command?.Execute(cachedMenuItem.CommandParameter); - } - } - - private static string MapInputToGestureKey(AcceleratorKeyEventArgs args) - { - var isCtrlDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down); - var isShiftDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down); - - if (!isCtrlDown && !isShiftDown) - { - return null; - } - - StringBuilder gestureKeyBuilder = new StringBuilder(); - - if (isCtrlDown) - { - gestureKeyBuilder.Append(CtrlValue); - gestureKeyBuilder.Append("+"); - } - - if (isShiftDown) - { - gestureKeyBuilder.Append(ShiftValue); - gestureKeyBuilder.Append("+"); - } - - if (args.VirtualKey == VirtualKey.None) - { - gestureKeyBuilder.Remove(gestureKeyBuilder.Length - 1, 1); - } - else - { - gestureKeyBuilder.Append(args.VirtualKey); - } - - return gestureKeyBuilder.ToString(); - } - - private static void InputGestureTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) - { - var inputGestureValue = e.NewValue as string; - if (string.IsNullOrEmpty(inputGestureValue) || MenuItemInputGestureCache.ContainsKey(inputGestureValue)) - { - return; - } - - var menuItem = (MenuFlyoutItem)obj; - MenuItemInputGestureCache.Add(inputGestureValue.ToUpper(), menuItem); - } - - public static string GetInputGestureText(MenuFlyoutItem obj) - { - return (string)obj.GetValue(InputGestureTextProperty); - } - - public static void SetInputGestureText(MenuFlyoutItem obj, string value) - { - obj.SetValue(InputGestureTextProperty, value); - } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs index 64c6e08cc35..9af60a5a8cf 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenuItem.cs @@ -26,9 +26,9 @@ public string Header public ClassicMenuItem() { DefaultStyleKey = typeof(ClassicMenuItem); + IsFocusEngagementEnabled = true; } - public void ShowMenu() { _flyoutButton?.Flyout?.ShowAt(_flyoutButton); @@ -60,7 +60,6 @@ protected override void OnApplyTemplate() _flyoutButton.Flyout = menuFlyout; } - base.OnApplyTemplate(); } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj index e84810a7a8d..451e410f4c8 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj @@ -55,6 +55,8 @@ + + From b1d7520b2d0d6829f7e3dbbd903a685ed86b9496 Mon Sep 17 00:00:00 2001 From: "DESKTOP-QJU4N0L\\mityh" Date: Sun, 9 Apr 2017 13:12:32 +1000 Subject: [PATCH 03/61] #981 fixing double navigation issue --- .../Microsoft.Toolkit.Uwp.SampleApp.csproj | 2 +- .../ClassicMenu/ClassicMenuPage.xaml | 76 ++++++++++++++----- .../ClassicMenu/ClassicMenuPage.xaml.cs | 66 +--------------- .../ClassicMenu/Commands/VsCommands.cs | 58 ++++++++++++++ .../SamplePages/ClassicMenu/DialogCommand.cs | 26 ------- .../ClassicMenu/ClassicMenu.Logic.cs | 35 +-------- .../ClassicMenu/ClassicMenu.cs | 40 +++++++++- .../ClassicMenu/ClassicMenu.xaml | 5 +- .../ClassicMenu/ClassicMenuItem.cs | 14 ++-- 9 files changed, 167 insertions(+), 155 deletions(-) create mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/Commands/VsCommands.cs delete mode 100644 Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj index cb7d6ceeab1..c586b7e939e 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj +++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj @@ -404,7 +404,7 @@ ClassicMenuPage.xaml - + NetworkHelperPage.xaml diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml index c86771679f3..1ba25a65548 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml @@ -2,39 +2,79 @@ x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ClassicMenuPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" - xmlns:wrapPanel="using:Microsoft.Toolkit.Uwp.UI.Controls.WrapPanel" - xmlns:classicMenu="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ClassicMenu" + xmlns:commands="using:Microsoft.Toolkit.Uwp.SampleApp.ClassicMenu.Commands" mc:Ignorable="d"> - + + + - - - - - + + + + + + + + + + + - + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs index c0ff9a3cf5f..671963012fa 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/ClassicMenuPage.xaml.cs @@ -1,74 +1,12 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI.Popups; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Navigation; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 +using Windows.UI.Xaml.Controls; namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages { - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// public sealed partial class ClassicMenuPage : Page { public ClassicMenuPage() { - this.InitializeComponent(); - //Loaded += ClassicMenuPage_Loaded; - } - - private void ClassicMenuPage_Loaded(object sender, RoutedEventArgs e) - { - //deep. - //deep.ContextFlyout.ShowAt(butttton); - //butttton.Flyout.ShowAt(butttton); - //butttton.Flyout.fl - //Flyout.ShowAttachedFlyout(butttton); - } - - private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e) - { - //// Create the message dialog and set its content - //var messageDialog = new MessageDialog("No internet connection has been found."); - - //// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers - //messageDialog.Commands.Add(new UICommand( - // "Try again", - // new UICommandInvokedHandler(this.CommandInvokedHandler))); - //messageDialog.Commands.Add(new UICommand( - // "Close", - // new UICommandInvokedHandler(this.CommandInvokedHandler))); - - //// Set the command that will be invoked by default - //messageDialog.DefaultCommandIndex = 0; - - //// Set the command to be invoked when escape is pressed - //messageDialog.CancelCommandIndex = 1; - - //// Show the message dialog - //await messageDialog.ShowAsync(); - - //var dialog = new MessageDialog("Your message here"); - //await dialog.ShowAsync(); - } - - private void CommandInvokedHandler(IUICommand command) - { - // Display message showing the label of the command that was invoked - //rootPage.NotifyUser("The '" + command.Label + "' command has been selected.", - // NotifyType.StatusMessage); + InitializeComponent(); } } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/Commands/VsCommands.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/Commands/VsCommands.cs new file mode 100644 index 00000000000..fe78e6356d8 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/Commands/VsCommands.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.UI.Popups; + +namespace Microsoft.Toolkit.Uwp.SampleApp.ClassicMenu.Commands +{ + internal class NewProjectCommand : ICommand + { + public bool CanExecute(object parameter) + { + return true; + } + + public async void Execute(object parameter) + { + var dialog = new MessageDialog("Create New Project"); + await dialog.ShowAsync(); + } + + public event EventHandler CanExecuteChanged; + } + + internal class NewFileCommand : ICommand + { + public bool CanExecute(object parameter) + { + return true; + } + + public async void Execute(object parameter) + { + var dialog = new MessageDialog("Create New File"); + await dialog.ShowAsync(); + } + + public event EventHandler CanExecuteChanged; + } + + internal class GenericCommand : ICommand + { + public bool CanExecute(object parameter) + { + return true; + } + + public async void Execute(object parameter) + { + var dialog = new MessageDialog(parameter.ToString()); + await dialog.ShowAsync(); + } + + public event EventHandler CanExecuteChanged; + } +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs deleted file mode 100644 index d3c59a8fbd3..00000000000 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ClassicMenu/DialogCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.UI.Popups; - -namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ClassicMenu -{ - public class DialogCommand : ICommand - { - public bool CanExecute(object parameter) - { - return true; - } - - public async void Execute(object parameter) - { - var dialog = new MessageDialog("Your message here"); - await dialog.ShowAsync(); - } - - public event EventHandler CanExecuteChanged; - } -} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs index fb0f91abc6b..4071b13108f 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.Logic.cs @@ -14,7 +14,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls { public partial class ClassicMenu { - private static bool NavigateThrowMenuHeader(AcceleratorKeyEventArgs args, ClassicMenu menu, ClassicMenuItem menuItem, Orientation orientation) + private static bool NavigateThrowMenuHeader(KeyEventArgs args, ClassicMenu menu, ClassicMenuItem menuItem, Orientation orientation) { if (orientation == Orientation.Horizontal) { @@ -74,7 +74,7 @@ private static bool NavigateThrowMenuHeader(AcceleratorKeyEventArgs args, Classi return false; } - private static string MapInputToGestureKey(AcceleratorKeyEventArgs args) + private static string MapInputToGestureKey(KeyEventArgs args) { var isCtrlDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down); var isShiftDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down); @@ -109,36 +109,5 @@ private static string MapInputToGestureKey(AcceleratorKeyEventArgs args) return gestureKeyBuilder.ToString(); } - - private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args) - { - if (args.VirtualKey == VirtualKey.Menu && !args.KeyStatus.WasKeyDown) - { - Focus(FocusState.Programmatic); - } - - var element = FocusManager.GetFocusedElement(); - var menuItem = element as ClassicMenuItem; - if (menuItem != null) - { - if (NavigateThrowMenuHeader(args, this, menuItem, Orientation)) - { - return; - } - } - - string gestureKey = MapInputToGestureKey(args); - - if (gestureKey == null) - { - return; - } - - if (MenuItemInputGestureCache.ContainsKey(gestureKey)) - { - var cachedMenuItem = MenuItemInputGestureCache[gestureKey]; - cachedMenuItem.Command?.Execute(cachedMenuItem.CommandParameter); - } - } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs index f2287c14b2f..21bd2ddf611 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.cs @@ -51,10 +51,7 @@ public ClassicMenu() protected override void OnApplyTemplate() { Loaded -= ClassicMenu_Loaded; - Dispatcher.AcceleratorKeyActivated -= Dispatcher_AcceleratorKeyActivated; - Loaded += ClassicMenu_Loaded; - Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated; base.OnApplyTemplate(); } @@ -62,6 +59,43 @@ private void ClassicMenu_Loaded(object sender, RoutedEventArgs e) { var wrapPanel = (WrapPanel.WrapPanel)ItemsPanelRoot; wrapPanel.Orientation = Orientation; + + Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated; + Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown; + } + + private void CoreWindow_KeyDown(CoreWindow sender, KeyEventArgs args) + { + var element = FocusManager.GetFocusedElement(); + var menuItem = element as ClassicMenuItem; + if (menuItem != null) + { + if (NavigateThrowMenuHeader(args, this, menuItem, Orientation)) + { + return; + } + } + + string gestureKey = MapInputToGestureKey(args); + + if (gestureKey == null) + { + return; + } + + if (MenuItemInputGestureCache.ContainsKey(gestureKey)) + { + var cachedMenuItem = MenuItemInputGestureCache[gestureKey]; + cachedMenuItem.Command?.Execute(cachedMenuItem.CommandParameter); + } + } + + private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args) + { + if (args.VirtualKey == VirtualKey.Menu && !args.KeyStatus.WasKeyDown) + { + Focus(FocusState.Keyboard); + } } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml index 1aae15b2c01..e41c1d7ff91 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml @@ -8,7 +8,7 @@ - + @@ -23,11 +23,12 @@ @@ -20,8 +25,10 @@ - - + + - + - + - + - + - + diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml index d33d0ac38ef..de5012151c0 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ClassicMenu/ClassicMenu.xaml @@ -8,7 +8,7 @@ - + @@ -31,6 +31,7 @@