C#/ WPF:KeyBinding不触发命令

时间:2010-10-15 10:30:54

标签: c# wpf icommand

我已宣布<InputBindings>

<UserControl.InputBindings>
    <KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding CopyImageCommand}" />
    <KeyBinding Key="V" Modifiers="Ctrl" Command="{Binding PasteImageCommand}" />
</UserControl.InputBindings>

出于测试目的,我也添加了绑定到这些命令的按钮

<Button Command="{Binding CopyImageCommand}" Content="Copy" />
<Button Command="{Binding PasteImageCommand}" Content="Paste" />

我注意到当启用粘贴按钮时,按Ctrl-V时没有任何反应。 Ctrl-C似乎工作。为此,选择了一个列表框项目,我不确定它是否有任何区别。任何人都知道为什么我的PasteImageCommand没有触发?

我使用的是.NET 4 btw

更新

更全面的代码snipplet

<UserControl x:Class="QuickImageUpload.Views.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:vm="clr-namespace:QuickImageUpload.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.InputBindings>
        <KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding CopyImageCommand}" />
        <KeyBinding Key="V" Modifiers="Ctrl" Command="{Binding PasteImageCommand}" />
    </UserControl.InputBindings>
    <UserControl.DataContext>
        <vm:ShellViewModel />
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />

更新

我发现我需要将KeyBindings放在MainWindow中,但命令在ViewModel中,如何在ShellView中设置键绑定然后绑定到命令在ShellViewModel

6 个答案:

答案 0 :(得分:6)

确保您没有绑定错误。您设置用户控件的DataContext,但请确保命令可以绑定到它。有时,WPF只使用外观顺序,然后在命令之后设置DataContext。

VS的输出窗口可能已显示命令的绑定错误。尝试将DataContext定义放在最前面(并教导自己为所有视图执行此操作)。

答案 1 :(得分:3)

为了避免硬编码的KeyBindings,我派出了Josh Smiths RelayCommand-Class并添加了与Shortcut相关的东西:

class UIRelayCommand : RelayCommand, INotifyPropertyChanged
{
    private static Dictionary<ModifierKeys, string> modifierText = new Dictionary<ModifierKeys, string>()
    {
        {ModifierKeys.None,""},
        {ModifierKeys.Control,"Ctrl+"},
        {ModifierKeys.Control|ModifierKeys.Shift,"Ctrl+Shift+"},
        {ModifierKeys.Control|ModifierKeys.Alt,"Ctrl+Alt+"},
        {ModifierKeys.Control|ModifierKeys.Shift|ModifierKeys.Alt,"Ctrl+Shift+Alt+"},
        {ModifierKeys.Windows,"Win+"}
    };

    private Key _key;
    public Key Key
    {
        get { return _key; }
        set { _key = value; RaisePropertyChanged("Key"); RaisePropertyChanged("GestureText"); }
    }

    private ModifierKeys _modifiers;
    public ModifierKeys Modifiers
    {
        get { return _modifiers; }
        set { _modifiers = value; RaisePropertyChanged("Modifiers"); RaisePropertyChanged("GestureText");}
    }

    public string GestureText
    {
        get { return modifierText[_modifiers] + _key.ToString(); }
    }

    public UIRelayCommand(Action<object> execute, Predicate<object> canExecute, Key key, ModifierKeys modifiers)
        : base(execute, canExecute)
    {
        _key = key;
        _modifiers = modifiers;
    }


    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

然后在ViewModel中创建命令:

private ICommand _newFileCommand;
public ICommand NewFileCommand
{
    get
    {
        if (_newFileCommand == null)
            _newFileCommand = new UIRelayCommand(p => OnNewFile(p), p => CanNewFile(p), Key.N, ModifierKeys.Control);
        return _newFileCommand;
    }
}
protected void OnNewFile(object p)
{
    //open file...
}
protected bool CanNewFile(object p)
{
    return true;
}

并在视图中绑定它:

<Window.InputBindings>
    <KeyBinding Command="{Binding NewFileCommand}" Key="{Binding NewFileCommand.Key}" Modifiers="{Binding NewFileCommand.Modifiers}"  />
</Window.InputBindings>
...
<MenuItem Header="New File" Command="{Binding NewFileCommand}" InputGestureText="{Binding NewFileCommand.GestureText}" />

通过这种方法,我可以允许用户在运行时调整快捷方式(在我的配置窗口中)

答案 2 :(得分:0)

您使用的是3.5还是4?

3.5其“功能”。 UserControl.InputBindings不是dataContext树的一部分,因此您无法绑定绑定到父级的类的项。例如。 DataBinding不起作用,您需要手动在代码中设置DataBinding或整个KeyBinding。

固定在4。

答案 3 :(得分:0)

我遇到类似的情况,其中Key相关事件仅在Shell View中被收听,并且没有调到按下该键的实际视图。 为了解决这个问题,我编写了一个小的附加行为来将焦点设置为用户控件或框架元素以接收对初始加载的关注,并且通过我想要监听的UI元素来监听关键笔划。 / p>

public class FocusBehavior
{
    public static readonly DependencyProperty IsFocusedProperty = 
        DependencyProperty.RegisterAttached("IsFocused", typeof(bool?),typeof(FocusBehavior),
        new UIPropertyMetadata(false, new PropertyChangedCallback(OnFocusChanged)));
    public static bool? GetIsFocused(DependencyObject obj)
    {
        return (bool?)obj.GetValue(IsFocusedProperty);
    }
    public static void SetIsFocused(DependencyObject obj, bool? value)
    {
        obj.SetValue(IsFocusedProperty, value);
    }
    private static void OnFocusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var frameworkElement = sender as FrameworkElement;
        if (frameworkElement == null) return;
        if (args.OldValue == null) return;
        if (args.NewValue == null) return;
        if ((bool)args.NewValue)
        {
            frameworkElement.Loaded += OnFrameworkElementLoaded;
        }
    }

    private static void OnFrameworkElementLoaded(object sender, RoutedEventArgs args)
    {
        var frameworkElement = sender as FrameworkElement;
        frameworkElement.Focus();
        frameworkElement.Loaded -= OnFrameworkElementLoaded;
        var textControl = frameworkElement as JHATextEditor;
        if (textControl == null) return;
        textControl.SelectAll();
    }
}

在我的一个列表视图中使用它,如下所示 -

<GridViewColumn Width="Auto" Header="Value">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid HorizontalAlignment="Stretch" MinWidth="100">
                                <TextBlock Text="{Binding FieldValue}" />
                            </Grid>
                            <DataTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsSelected}" Value="True">
                                    <Setter Property="local:FocusBehavior.IsFocused" TargetName="FieldValueEditor" Value="True" />
                                </DataTrigger>
                            </DataTemplate.Triggers>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

希望这有帮助。

-VJ

答案 4 :(得分:0)

在这种情况下,您可以在RoutedCommand声明中提供键绑定:

public static RoutedCommand PasteImageCommand = new RoutedCommand("PasteImageCommand", typeof(YourType), new InputGestureCollection { new KeyGesture(Key.V, ModifierKeys.Control)});

这应该有用。

答案 5 :(得分:0)

试试这个:

<UserControl.InputBindings>
        <KeyBinding Key="C" Modifiers="Control" Command="{Binding CopyImageCommand}" />
        <KeyBinding Key="V" Modifiers="Control" Command="{Binding PasteImageCommand}" />
    </UserControl.InputBindings>