【问题标题】:How to bind hotkeys to generic buttons?如何将热键绑定到通用按钮?
【发布时间】:2019-11-19 10:51:00
【问题描述】:

我有一个在运行时创建按钮的用户控件。我通过单击按钮使按钮与命令绑定一起工作有没有办法使用热键触发按钮,例如 ctrl+R,一旦我到达 TakeC 命令,我需要知道按下了什么命令?

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; }
}

【问题讨论】:

  • 首先,你有什么问题?命令键绑定不起作用,或者您想了解调用命令的方式,例如通过按鼠标按钮或热键?
  • @PavelAnikhouski 我的热键没有触发命令,我现在有 3 个热键 ctrl+R、ctrl+T、ctrl+Y,我想当我按下它触发的任何键时我的命令(TakeC)。
  • 您绑定到TakeC,但您的属性名为TakeCCommand?这是没有意义的。还有,按CTRL+R的时候焦点在哪里?
  • @mm8 我已经解决了TakeC,你说的重点在哪里是什么意思?你知道任何关于带有通用按钮的热键的好教程吗?我以前没有使用过热键。我还尝试了&lt;Button.InputBindings&gt; 而不是Usercontrol,因为该命令位于按钮上。
  • “通用”按钮是什么意思? KeyBinding 是否起作用取决于您按下按键时具有焦点的控件。

标签: c# wpf


【解决方案1】:

KeyBindings 仅在您应用它们的元素被聚焦时才起作用:

Keybindings without any focus

根据您的要求,更好的方法可能是为UserControl 的父窗口处理PreviewKeyDown 事件。像这样的:

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();
        }
    }
}

然后,“热键”将不管窗口中当前聚焦的元素起作用。

您可以将其包装在附加行为中,以便在多个 UserControls 中重复使用,但如何做到这一点是另一个故事,与您的实际问题没有直接关系。

【讨论】:

    猜你喜欢
    • 2011-03-19
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    相关资源
    最近更新 更多