Reputation: 690
In my WPF application a "global" search box appears when hitting Ctrl+Space. It behaves like Spotlight in Mac OS when hitting Command+Space.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public static RoutedCommand OpenSpotlight { get; set; } = new RoutedCommand();
public MainWindow()
{
OpenSpotlight.InputGestures.Add(new KeyGesture(Key.Space, ModifierKeys.Control));
}
private void OpenSpotlight_Execute(object sender, ExecutedRoutedEventArgs e)
{
// Code which opens the search box ...
}
}
MainWindow.xaml
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.OpenSpotlight}" Executed="OpenSpotlight_Execute"/>
</Window.CommandBindings>
Works fine, except one problem: when any button is focused, hitting Ctrl+Space triggers the button to be clicked because Space key is being hit.
Is there any way to omit this behaviour? I think of changing/removing the focus globally when Ctrl key is hit but don't know how this can be implemented ...
Upvotes: 1
Views: 80
Reputation: 169340
Instead of using a RoutedCommand
and a CommandBinding
, you could just handle the PreviewKeyDown
event:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PreviewKeyDown += OnPreviewKeyDown;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space
&& (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
e.Handled = true;
// Code which opens the search box ...
}
}
}
This solution doesn't require you to add anything to the XAML markup.
Upvotes: 3
Reputation: 5748
I haven't tried this, but seems quite logical to me.
You can handle the KeyDown
and/or PreviewKeyDown
event of a button and skip the Space
press. Something like this could work :
private void GlobalButton_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
Wondering how you'ld do this for all the buttons? Here's a function to find a control of a given type:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T :
DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Simply loop through the buttons on window_load
or similar events:
foreach (Button btn in FindVisualChildren<Button>(this))
{
btn.KeyDown += GlobalButton_PreviewKeyDown;
btn.PreviewKeyDown += GlobalButton_PreviewKeyDown;
}
Hopefully this helps.
Upvotes: 1