Display Key Mappings in Settings (#2314)

* Move changes

* Display Key Mapping in Settings

* Fix display of empty keys list

Co-authored-by: Udit Singh <udsing@microsoft.com>
This commit is contained in:
Tomas Agustin Raies 2020-04-22 14:55:45 -07:00 committed by GitHub
parent ca3a436fe5
commit d941b31c45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 269 additions and 118 deletions

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
@ -32,6 +32,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
public bool PowerRename { get; set; } public bool PowerRename { get; set; }
[JsonPropertyName("Keyboard Manager")]
public bool KeyboardManager { get; set; }
public string ToJsonString() public string ToJsonString()
{ {
return JsonSerializer.Serialize(this); return JsonSerializer.Serialize(this);

View File

@ -7,12 +7,18 @@ using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Lib namespace Microsoft.PowerToys.Settings.UI.Lib
{ {
public class KeyboadManagerConfigModel public class KeyboardManagerProfile
{ {
[JsonPropertyName("remapKeys")] [JsonPropertyName("remapKeys")]
public RemapKeysDataModel RemapKeys { get; set; } public RemapKeysDataModel RemapKeys { get; set; }
[JsonPropertyName("remapShortcuts")] [JsonPropertyName("remapShortcuts")]
public ShortcutsKeyDataModel RemapShortcuts { get; set; } public ShortcutsKeyDataModel RemapShortcuts { get; set; }
public KeyboardManagerProfile()
{
RemapKeys = new RemapKeysDataModel();
RemapShortcuts = new ShortcutsKeyDataModel();
}
} }
} }

View File

@ -2,6 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Lib.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Lib namespace Microsoft.PowerToys.Settings.UI.Lib
@ -13,5 +16,24 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
[JsonPropertyName("newRemapKeys")] [JsonPropertyName("newRemapKeys")]
public string NewRemapKeys { get; set; } public string NewRemapKeys { get; set; }
private List<string> MapKeys(string stringOfKeys)
{
return stringOfKeys
.Split(';')
.Select(uint.Parse)
.Select(Helper.GetKeyName)
.ToList();
}
public List<string> GetOriginalKeys()
{
return MapKeys(OriginalKeys);
}
public List<string> GetNewRemapKeys()
{
return MapKeys(NewRemapKeys);
}
} }
} }

View File

@ -11,5 +11,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{ {
[JsonPropertyName("inProcess")] [JsonPropertyName("inProcess")]
public List<KeysDataModel> InProcessRemapKeys { get; set; } public List<KeysDataModel> InProcessRemapKeys { get; set; }
public RemapKeysDataModel()
{
InProcessRemapKeys = new List<KeysDataModel>();
}
} }
} }

View File

@ -41,7 +41,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
$"Microsoft\\PowerToys\\{powertoy}\\{fileName}"); $"Microsoft\\PowerToys\\{powertoy}\\{fileName}");
} }
public static bool SettingsExists(string powertoy, string fileName = DefaultFileName) public static bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName)
{ {
return File.Exists(GetSettingsPath(powertoy, fileName)); return File.Exists(GetSettingsPath(powertoy, fileName));
} }

View File

@ -11,5 +11,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{ {
[JsonPropertyName("global")] [JsonPropertyName("global")]
public List<KeysDataModel> GlobalRemapShortcuts { get; set; } public List<KeysDataModel> GlobalRemapShortcuts { get; set; }
public ShortcutsKeyDataModel()
{
GlobalRemapShortcuts = new List<KeysDataModel>();
}
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -71,11 +71,9 @@
<Compile Include="ViewModels\FancyZonesViewModel.cs" /> <Compile Include="ViewModels\FancyZonesViewModel.cs" />
<Compile Include="ViewModels\ImageResizerViewModel.cs" /> <Compile Include="ViewModels\ImageResizerViewModel.cs" />
<Compile Include="ViewModels\KeyboardManagerViewModel.cs" /> <Compile Include="ViewModels\KeyboardManagerViewModel.cs" />
<Compile Include="ViewModels\Keys.cs" />
<Compile Include="ViewModels\PowerPreviewViewModel.cs" /> <Compile Include="ViewModels\PowerPreviewViewModel.cs" />
<Compile Include="ViewModels\PowerRenameViewModel.cs" /> <Compile Include="ViewModels\PowerRenameViewModel.cs" />
<Compile Include="ViewModels\PowerLauncherViewModel.cs" /> <Compile Include="ViewModels\PowerLauncherViewModel.cs" />
<Compile Include="ViewModels\RemapKeysModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" /> <Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\ShortcutGuideViewModel.cs" /> <Compile Include="ViewModels\ShortcutGuideViewModel.cs" />
<Compile Include="Views\GeneralPage.xaml.cs"> <Compile Include="Views\GeneralPage.xaml.cs">
@ -105,6 +103,7 @@
<Compile Include="Views\ShortcutGuidePage.xaml.cs"> <Compile Include="Views\ShortcutGuidePage.xaml.cs">
<DependentUpon>ShortcutGuidePage.xaml</DependentUpon> <DependentUpon>ShortcutGuidePage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\VisibleIfNotEmpty.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AppxManifest Include="Package.appxmanifest"> <AppxManifest Include="Package.appxmanifest">

View File

@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
@ -11,6 +13,9 @@ using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib;
using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.Utilities;
using Microsoft.PowerToys.Settings.UI.Views; using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.UI.Core;
using Windows.UI.Xaml;
namespace Microsoft.PowerToys.Settings.UI.ViewModels namespace Microsoft.PowerToys.Settings.UI.ViewModels
{ {
@ -22,24 +27,31 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private const string EditShortcutActionName = "EditShortcut"; private const string EditShortcutActionName = "EditShortcut";
private const string EditShortcutActionValue = "Open Edit Shortcut Window"; private const string EditShortcutActionValue = "Open Edit Shortcut Window";
private const string JsonFileType = ".json"; private const string JsonFileType = ".json";
private const string ConfigFileMutexName = "PowerToys.KeyboardManager.ConfigMutex"; private const string ProfileFileMutexName = "PowerToys.KeyboardManager.ConfigMutex";
private const int ConfigFileMutexWaitTimeoutMiliSeconds = 1000; private const int ProfileFileMutexWaitTimeoutMilliseconds = 1000;
private readonly CoreDispatcher dispatcher;
private readonly FileSystemWatcher watcher;
private ICommand remapKeyboardCommand; private ICommand remapKeyboardCommand;
private ICommand editShortcutCommand; private ICommand editShortcutCommand;
private FileSystemWatcher watcher;
private KeyboardManagerSettings settings; private KeyboardManagerSettings settings;
private KeyboardManagerProfile profile;
public ICommand RemapKeyboardCommand => remapKeyboardCommand ?? (remapKeyboardCommand = new RelayCommand(OnRemapKeyboard)); private GeneralSettings generalSettings;
public ICommand EditShortcutCommand => editShortcutCommand ?? (editShortcutCommand = new RelayCommand(OnEditShortcut));
public KeyboardManagerViewModel() public KeyboardManagerViewModel()
{ {
dispatcher = Window.Current.Dispatcher;
if (SettingsUtils.SettingsExists(PowerToyName)) if (SettingsUtils.SettingsExists(PowerToyName))
{ {
// Todo: Be more resillent while reading and saving settings. // Todo: Be more resillent while reading and saving settings.
settings = SettingsUtils.GetSettings<KeyboardManagerSettings>(PowerToyName); settings = SettingsUtils.GetSettings<KeyboardManagerSettings>(PowerToyName);
// Load profile.
if (!LoadProfile())
{
profile = new KeyboardManagerProfile();
}
} }
else else
{ {
@ -47,8 +59,77 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SettingsUtils.SaveSettings(settings.ToJsonString(), PowerToyName); SettingsUtils.SaveSettings(settings.ToJsonString(), PowerToyName);
} }
watcher = Helper.GetFileWatcher(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType, OnConfigFileUpdate); if (SettingsUtils.SettingsExists())
{
generalSettings = SettingsUtils.GetSettings<GeneralSettings>(string.Empty);
} }
else
{
generalSettings = new GeneralSettings();
SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty);
}
watcher = Helper.GetFileWatcher(
PowerToyName,
settings.Properties.ActiveConfiguration.Value + JsonFileType,
OnConfigFileUpdate);
}
public bool Enabled
{
get
{
return generalSettings.Enabled.KeyboardManager;
}
set
{
if (generalSettings.Enabled.KeyboardManager != value)
{
generalSettings.Enabled.KeyboardManager = value;
OnPropertyChanged(nameof(Enabled));
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(generalSettings);
ShellPage.DefaultSndMSGCallback(outgoing.ToString());
}
}
}
// store remappings
public List<KeysDataModel> RemapKeys
{
get
{
if (profile != null)
{
return profile.RemapKeys.InProcessRemapKeys;
}
else
{
return new List<KeysDataModel>();
}
}
}
public List<KeysDataModel> RemapShortcuts
{
get
{
if (profile != null)
{
return profile.RemapShortcuts.GlobalRemapShortcuts;
}
else
{
return new List<KeysDataModel>();
}
}
}
public ICommand RemapKeyboardCommand => remapKeyboardCommand ?? (remapKeyboardCommand = new RelayCommand(OnRemapKeyboard));
public ICommand EditShortcutCommand => editShortcutCommand ?? (editShortcutCommand = new RelayCommand(OnEditShortcut));
private async void OnRemapKeyboard() private async void OnRemapKeyboard()
{ {
@ -74,38 +155,54 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
await Task.CompletedTask; await Task.CompletedTask;
} }
private void OnConfigFileUpdate() private async void OnConfigFileUpdate()
{ {
// Note: FileSystemWatcher raise notification mutiple times for single update operation. // Note: FileSystemWatcher raise notification mutiple times for single update operation.
// Todo: Handle duplicate events either by somehow supress them or re-read the configuration everytime since we will be updating the UI only if something is changed. // Todo: Handle duplicate events either by somehow supress them or re-read the configuration everytime since we will be updating the UI only if something is changed.
GetKeyboardManagerConfigFile(); if (LoadProfile())
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
OnPropertyChanged(nameof(RemapKeys));
OnPropertyChanged(nameof(RemapShortcuts));
});
}
} }
private void GetKeyboardManagerConfigFile() private bool LoadProfile()
{ {
var success = true;
try try
{ {
using (var configFileMutex = Mutex.OpenExisting(ConfigFileMutexName)) using (var profileFileMutex = Mutex.OpenExisting(ProfileFileMutexName))
{ {
if (configFileMutex.WaitOne(ConfigFileMutexWaitTimeoutMiliSeconds)) if (profileFileMutex.WaitOne(ProfileFileMutexWaitTimeoutMilliseconds))
{ {
// update the UI element here. // update the UI element here.
try try
{ {
var config = SettingsUtils.GetSettings<KeyboadManagerConfigModel>(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType); profile = SettingsUtils.GetSettings<KeyboardManagerProfile>(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType);
} }
finally finally
{ {
// Make sure to release the mutex. // Make sure to release the mutex.
configFileMutex.ReleaseMutex(); profileFileMutex.ReleaseMutex();
} }
} }
else
{
success = false;
}
} }
} }
catch (Exception) catch (Exception)
{ {
// Failed to load the configuration. // Failed to load the configuration.
success = false;
} }
return success;
} }
} }
} }

View File

@ -1,13 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class Keys
{
public string From { get; set; }
public string To { get; set; }
}
}

View File

@ -1,24 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.ObjectModel;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
// Dummy data model for the UI. Will be removed moving forward.
public class RemapKeysModel : ObservableCollection<Keys>
{
public RemapKeysModel()
{
Add(new Keys { From = "A", To = "B" });
Add(new Keys { From = "B", To = "A" });
Add(new Keys { From = "Ctrl", To = "Shift" });
Add(new Keys { From = "Shift", To = "Ctrl" });
Add(new Keys { From = "A", To = "B" });
Add(new Keys { From = "B", To = "B" });
Add(new Keys { From = "Ctrl", To = "Shift" });
Add(new Keys { From = "Shift", To = "Ctrl" });
}
}
}

View File

@ -7,58 +7,79 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="using:Microsoft.PowerToys.Settings.UI.ViewModels" xmlns:viewModel="using:Microsoft.PowerToys.Settings.UI.ViewModels"
xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions" xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions"
xmlns:Lib="using:Microsoft.PowerToys.Settings.UI.Lib"
mc:Ignorable="d" mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources> <Page.Resources>
<viewModel:RemapKeysModel x:Key="dummyData"/>
<viewModel:KeyboardManagerViewModel x:Key="eventViewModel"/> <viewModel:KeyboardManagerViewModel x:Key="eventViewModel"/>
<local:VisibleIfNotEmpty x:Key="visibleIfNotEmptyConverter" />
<DataTemplate x:Name="KeysListViewTemplate" x:DataType="viewModel:RemapKeysModel"> <DataTemplate x:Name="KeysListViewTemplate" x:DataType="Lib:KeysDataModel">
<Grid Height="56"> <StackPanel
<Grid.ColumnDefinitions> Orientation="Horizontal"
<ColumnDefinition Width="80"/> Height="56">
<ColumnDefinition Width="80"/> <ItemsControl
<ColumnDefinition Width="120"/> ItemsSource="{x:Bind GetOriginalKeys()}">
</Grid.ColumnDefinitions> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border <Border
Background="{ThemeResource SystemBaseLowColor}" Background="{ThemeResource SystemBaseLowColor}"
CornerRadius="4" CornerRadius="4"
Grid.Column="0"
Padding="14,0,14,0" Padding="14,0,14,0"
Margin="0,0,0,0" Margin="5,0,5,0"
Height="36" Height="36"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Left"> HorizontalAlignment="Left">
<TextBlock FontWeight="SemiBold" <TextBlock
FontWeight="SemiBold"
VerticalAlignment="Center" VerticalAlignment="Center"
TextAlignment="Center" TextAlignment="Center"
FontSize="12" FontSize="12"
Text="{Binding From}"> Text="{Binding}" />
</TextBlock>
</Border> </Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<FontIcon Glyph="&#xE72A;" <FontIcon Glyph="&#xE72A;"
Grid.Column="1" Grid.Column="1"
FontSize="14" FontSize="14"
VerticalAlignment="Center" /> VerticalAlignment="Center"
Margin="5,0,5,0"/>
<Border Background="{ThemeResource SystemAccentColor}" <ItemsControl
ItemsSource="{x:Bind GetNewRemapKeys()}"
Grid.Column="2">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
Background="{ThemeResource SystemAccentColor}"
CornerRadius="4" CornerRadius="4"
Grid.Column="2"
Padding="14,0,14,0" Padding="14,0,14,0"
Margin="20,0,0,0" Margin="5,0,5,0"
Height="36" Height="36"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Left"> HorizontalAlignment="Left">
<TextBlock FontWeight="SemiBold" <TextBlock
FontWeight="SemiBold"
VerticalAlignment="Center" VerticalAlignment="Center"
TextAlignment="Center" TextAlignment="Center"
Foreground="White" Foreground="White"
FontSize="12" FontSize="12"
Text="{Binding To}"> Text="{Binding}" />
</TextBlock>
</Border> </Border>
</Grid> </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate> </DataTemplate>
</Page.Resources> </Page.Resources>
@ -99,7 +120,7 @@
TextWrapping="Wrap"/> TextWrapping="Wrap"/>
<ToggleSwitch x:Uid="KeyboardManager_EnableToggle" <ToggleSwitch x:Uid="KeyboardManager_EnableToggle"
IsOn="True" IsOn="{x:Bind Path=ViewModel.Enabled, Mode=TwoWay}"
Margin="{StaticResource SmallTopMargin}" /> Margin="{StaticResource SmallTopMargin}" />
<!--<TextBlock x:Uid="KeyboardManager_ConfigHeader" <!--<TextBlock x:Uid="KeyboardManager_ConfigHeader"
@ -125,20 +146,24 @@
<Button x:Uid="KeyboardManager_RemapKeyboardButton" <Button x:Uid="KeyboardManager_RemapKeyboardButton"
Margin="{StaticResource SmallTopMargin}" Margin="{StaticResource SmallTopMargin}"
Style="{StaticResource ButtonRevealStyle}" Style="{StaticResource ButtonRevealStyle}"
Command="{Binding Path=RemapKeyboardCommand}"/> Command="{Binding Path=RemapKeyboardCommand}"
IsEnabled="{x:Bind Path=ViewModel.Enabled, Mode=OneWay}"/>
<ListView x:Name="RemapKeysList" <ListView x:Name="RemapKeysList"
extensions:ListViewExtensions.AlternateColor="{ThemeResource SystemControlBackgroundListLowBrush}" extensions:ListViewExtensions.AlternateColor="{ThemeResource SystemControlBackgroundListLowBrush}"
ItemsSource="{StaticResource dummyData}" ItemsSource="{x:Bind Path=ViewModel.RemapKeys, Mode=OneWay}"
ItemTemplate="{StaticResource KeysListViewTemplate}" ItemTemplate="{StaticResource KeysListViewTemplate}"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}" BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1" BorderThickness="1"
Width="350" CornerRadius="4"
MinWidth="350"
MaxHeight="200" MaxHeight="200"
Margin="{StaticResource MediumTopBottomMargin}" Margin="{StaticResource MediumTopBottomMargin}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
SelectionMode="None" SelectionMode="None"
IsSwipeEnabled="False"/> IsSwipeEnabled="False"
Visibility="{x:Bind Path=ViewModel.RemapKeys, Mode=OneWay, Converter={StaticResource visibleIfNotEmptyConverter}}"
/>
<TextBlock x:Uid="KeyboardManager_RemapShortcutsHeader" <TextBlock x:Uid="KeyboardManager_RemapShortcutsHeader"
@ -150,23 +175,25 @@
<Button x:Uid="KeyboardManager_RemapShortcutsButton" <Button x:Uid="KeyboardManager_RemapShortcutsButton"
Margin="{StaticResource SmallTopMargin}" Margin="{StaticResource SmallTopMargin}"
Style="{StaticResource ButtonRevealStyle}" Style="{StaticResource ButtonRevealStyle}"
Command="{Binding Path=EditShortcutCommand}"/> Command="{Binding Path=EditShortcutCommand}"
IsEnabled="{x:Bind Path=ViewModel.Enabled, Mode=OneWay}"
/>
<ListView x:Name="RemapShortcutsList" <ListView x:Name="RemapShortcutsList"
extensions:ListViewExtensions.AlternateColor="{ThemeResource SystemControlBackgroundListLowBrush}" extensions:ListViewExtensions.AlternateColor="{ThemeResource SystemControlBackgroundListLowBrush}"
ItemsSource="{StaticResource dummyData}" ItemsSource="{x:Bind Path=ViewModel.RemapShortcuts, Mode=OneWay}"
ItemTemplate="{StaticResource KeysListViewTemplate}" ItemTemplate="{StaticResource KeysListViewTemplate}"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}" BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1" BorderThickness="1"
CornerRadius="4" CornerRadius="4"
Width="350" MinWidth="350"
MaxHeight="200" MaxHeight="200"
Margin="{StaticResource MediumTopBottomMargin}" Margin="{StaticResource MediumTopBottomMargin}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
SelectionMode="None" SelectionMode="None"
IsSwipeEnabled="False"/> IsSwipeEnabled="False"
Visibility="{x:Bind Path=ViewModel.RemapShortcuts, Mode=OneWay, Converter={StaticResource visibleIfNotEmptyConverter}}"
/>
</StackPanel> </StackPanel>
<StackPanel <StackPanel

View File

@ -0,0 +1,24 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public class VisibleIfNotEmpty : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return (value as IList).Count == 0 ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return null;
}
}
}