1

I have a Usercontrol that creates buttons at run-time. I have made the buttons work with command bindings by clicking the buttons is there a way to trigger the buttons using hotkeys e.g ctrl+R and once I get to the TakeC command I need to know what command was pressed?

XAML:

<UserControl.InputBindings>
    <KeyBinding Command="{Binding TakeC, Source=self}"
          CommandParameter="{Binding }"
          Gesture="CTRL+R" />
</UserControl.InputBindings>
<StackPanel Orientation="Horizontal">
    <ItemsControl ItemsSource="{Binding CButtons}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Name="CButtonsPanel" CanVerticallyScroll="true" Orientation="Horizontal"/>
            </ItemsPanelTemplate>
       </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>

                    <Button Name="cTakeC" Content="{Binding Content}" Command="{Binding Path=TakeCCommand}" CommandParameter="{Binding}" Margin="5">
                        <FrameworkElement.Style>
                                <MultiBinding Converter="{StaticResource CButtonStyleConverter}">
                                <MultiBinding.Bindings>
                                    <Binding/>
                                    <Binding Path="IsActive"/>
                            </MultiBinding.Bindings>
                        </MultiBinding>
                    </FrameworkElement.Style>
                </Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

</StackPanel>

C#:

TakeCCommand = new RelayCommand(TakeC);

void TakeC(object parameter)
{
    ButtonViewModel<StyledButtonModel> myClass = parameter as ButtonViewModel<StyledButtonModel>;
    // All buttons gets here once clicked
    // I need to know what key was pressed here

}

public class StyledButtonModel 
{
    public string Name { get; set; } = "Ctrl+R"

    public CButtonStyle Styles { get; set; }
}
Dev
  • 1,780
  • 3
  • 18
  • 46
  • First of all, which problem do you have? Command key binding isn't working or you want to get the way how the command was invoked, e.g. by pressing the mouse button or hotkey? – Pavel Anikhouski Nov 19 '19 at 11:28
  • @PavelAnikhouski my hotkey is not triggering the command, I have 3 hotkeys at the moment ctrl+R, ctrl+T, ctrl+Y, I would like for when I press any of the keys it triggers my command(TakeC). – Dev Nov 19 '19 at 12:47
  • You bind to `TakeC` but your property is called `TakeCCommand`? This makes no sense. Also, where is the focus when you press CTRL+R? – mm8 Nov 19 '19 at 14:13
  • @mm8 I have resolved the `TakeC`, What do you mean by where is the focus? Do you know of any good tutorials on hotkeys with generic buttons? I have not used hotkeys before. I also tried `` instead of `Usercontrol` because the command is on a button. – Dev Nov 19 '19 at 15:27
  • What do you mean by "generic" buttons? Whether the `KeyBinding` will work depends on what control that has the focus when you press the keys. – mm8 Nov 19 '19 at 15:29

1 Answers1

1

KeyBindings will only work when the element to which you have applied them is focused:

Keybindings without any focus

Depending on your requirements, a better approach may be to handle the PreviewKeyDown event for the parent window of the UserControl. Something like this:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        Loaded += UserControl1_Loaded;
        Unloaded += UserControl1_Unloaded;
    }

    private void UserControl1_Loaded(object sender, RoutedEventArgs e)
    {
        Loaded -= UserControl1_Loaded;
        Window window = Window.GetWindow(this);
        window.PreviewKeyDown += Window_PreviewKeyDown;
    }

    private void UserControl1_Unloaded(object sender, RoutedEventArgs e)
    {
        Unloaded -= UserControl1_Unloaded;
        Window window = Window.GetWindow(this);
        window.PreviewKeyDown -= Window_PreviewKeyDown;
    }

    private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.R && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.LeftCtrl)))
        {
            var viewModel = DataContext as YourViewModel;
            if (viewModel != null)
                viewModel.TakeCCommand.Execute();
        }
    }
}

Then the "hotkey" will work regardess of what element is currently focused in the window.

You may wrap this in an attached behaviour for reuse across several UserControls but how to this is another story that is not directly related to your actual question.

mm8
  • 163,881
  • 10
  • 57
  • 88