[Hosts] Add Keyboard Shortcuts (#26019)

* added keyboard shortcuts

* use x:Bind
This commit is contained in:
Davide Giacometti 2023-06-05 14:08:41 +02:00 committed by GitHub
parent 4d5152f78a
commit d426d9afde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 124 additions and 14 deletions

View File

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using Hosts.Helpers;
using Microsoft.UI.Windowing;
using WinUIEx;
namespace Hosts

View File

@ -132,6 +132,9 @@
<data name="AddEntryBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>New entry</value>
</data>
<data name="AddEntryBtn.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>New entry (CTRL+N)</value>
</data>
<data name="AdditionalLinesBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Additional content</value>
</data>
@ -187,6 +190,9 @@
<data name="DuplicateEntryIcon.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Duplicate entry</value>
</data>
<data name="Edit.Text" xml:space="preserve">
<value>Edit</value>
</data>
<data name="Entries.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Entries</value>
</data>

View File

@ -56,6 +56,11 @@
Glyph="&#xe710;" />
<TextBlock x:Uid="AddEntry" />
</StackPanel>
<Button.KeyboardAccelerators>
<KeyboardAccelerator
Modifiers="Control"
Key="N" />
</Button.KeyboardAccelerators>
</Button>
<StackPanel
@ -195,8 +200,10 @@
CornerRadius="8"
IsItemClickEnabled="True"
ItemClick="Entries_ItemClick"
ItemsSource="{Binding Entries, Mode=TwoWay}"
SelectedItem="{Binding Selected, Mode=TwoWay}"
KeyDown="Entries_KeyDown"
GotFocus="Entries_GotFocus"
ItemsSource="{x:Bind ViewModel.Entries, Mode=TwoWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=TwoWay}"
Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource BoolToInvertedVisibilityConverter}, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Entry">
@ -213,11 +220,27 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyout Opened="MenuFlyout_Opened">
<MenuFlyoutItem
x:Uid="Edit"
Click="Edit_Click"
Icon="Edit">
<MenuFlyoutItem.KeyboardAccelerators>
<KeyboardAccelerator
Modifiers="Control"
Key="E" />
</MenuFlyoutItem.KeyboardAccelerators>
</MenuFlyoutItem>
<MenuFlyoutItem
x:Uid="Ping"
Click="Ping_Click"
Icon="TwoBars" />
Icon="TwoBars">
<MenuFlyoutItem.KeyboardAccelerators>
<KeyboardAccelerator
Modifiers="Control"
Key="P" />
</MenuFlyoutItem.KeyboardAccelerators>
</MenuFlyoutItem>
<MenuFlyoutItem
x:Uid="MoveUp"
Click="ReorderButtonUp_Click"
@ -238,7 +261,11 @@
<MenuFlyoutItem
x:Uid="Delete"
Click="Delete_Click"
Icon="Delete" />
Icon="Delete">
<MenuFlyoutItem.KeyboardAccelerators>
<KeyboardAccelerator Key="Delete" />
</MenuFlyoutItem.KeyboardAccelerators>
</MenuFlyoutItem>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
<TextBlock
@ -346,7 +373,7 @@
x:Name="EntryDialog"
x:Uid="EntryDialog"
Loaded="ContentDialog_Loaded_ApplyMargin"
IsPrimaryButtonEnabled="{Binding Valid, Mode=TwoWay}"
IsPrimaryButtonEnabled="{Binding Valid, Mode=OneWay}"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
<ContentDialog.DataContext>
<models:Entry />

View File

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;
@ -15,6 +16,8 @@ using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;
using Windows.ApplicationModel.Resources;
using Windows.System;
using Windows.UI.Core;
namespace Hosts.Views
{
@ -60,9 +63,14 @@ namespace Hosts.Views
}
private async void Entries_ItemClick(object sender, ItemClickEventArgs e)
{
await ShowEditDialogAsync(e.ClickedItem as Entry);
}
public async Task ShowEditDialogAsync(Entry entry)
{
var resourceLoader = ResourceLoader.GetForViewIndependentUse();
ViewModel.Selected = e.ClickedItem as Entry;
ViewModel.Selected = entry;
EntryDialog.Title = resourceLoader.GetString("UpdateEntry_Title");
EntryDialog.PrimaryButtonText = resourceLoader.GetString("UpdateBtn");
EntryDialog.PrimaryButtonCommand = UpdateCommand;
@ -111,21 +119,40 @@ namespace Hosts.Views
if (menuFlyoutItem != null)
{
var selectedEntry = menuFlyoutItem.DataContext as Entry;
ViewModel.Selected = selectedEntry;
DeleteDialog.Title = selectedEntry.Address;
await DeleteDialog.ShowAsync();
await ShowDeleteDialogAsync(menuFlyoutItem.DataContext as Entry);
}
}
public async Task ShowDeleteDialogAsync(Entry entry)
{
ViewModel.Selected = entry;
DeleteDialog.Title = entry.Address;
await DeleteDialog.ShowAsync();
}
private async void Ping_Click(object sender, RoutedEventArgs e)
{
var menuFlyoutItem = sender as MenuFlyoutItem;
if (menuFlyoutItem != null)
{
ViewModel.Selected = menuFlyoutItem.DataContext as Entry;
await ViewModel.PingSelectedAsync();
await PingAsync(menuFlyoutItem.DataContext as Entry);
}
}
private async Task PingAsync(Entry entry)
{
ViewModel.Selected = entry;
await ViewModel.PingSelectedAsync();
}
private async void Edit_Click(object sender, RoutedEventArgs e)
{
var menuFlyoutItem = sender as MenuFlyoutItem;
if (menuFlyoutItem != null)
{
await ShowEditDialogAsync(menuFlyoutItem.DataContext as Entry);
}
}
@ -197,5 +224,56 @@ namespace Hosts.Views
Logger.LogError("Couldn't set the margin for a content dialog. It will appear on top of the title bar.", ex);
}
}
/// <summary>
/// Handle the keyboard shortcuts at list view level since
/// KeyboardAccelerators in FlyoutBase.AttachedFlyout works only when the flyout is open
/// </summary>
private async void Entries_KeyDown(object sender, KeyRoutedEventArgs e)
{
var listView = sender as ListView;
if (listView != null && e.KeyStatus.WasKeyDown == false)
{
var entry = listView.SelectedItem as Entry;
if (Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down))
{
if (e.Key == VirtualKey.E)
{
await ShowEditDialogAsync(entry);
}
else if (e.Key == VirtualKey.P)
{
await PingAsync(entry);
}
}
else if (e.Key == VirtualKey.Delete)
{
await ShowDeleteDialogAsync(entry);
}
}
}
/// <summary>
/// Focus the first item when the list view gets the focus with keyboard
/// </summary>
private void Entries_GotFocus(object sender, RoutedEventArgs e)
{
var listView = sender as ListView;
if (listView.SelectedItem == null && listView.Items.Count > 0)
{
listView.SelectedIndex = 0;
}
}
private void MenuFlyout_Opened(object sender, object e)
{
// Focus the first item: required for workaround https://github.com/microsoft/PowerToys/issues/21263
var menuFlyout = sender as MenuFlyout;
if (menuFlyout != null && menuFlyout.Items.Count > 0)
{
menuFlyout.Items.First().Focus(FocusState.Programmatic);
}
}
}
}