10

我已经声明<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 顺便说一句

更新

更完整的代码片段

<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主窗口中,但命令在 中ViewModel,我如何在ShellView其中设置键绑定然后绑定到中的命令ShellViewModel

4

7 回答 7

6

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

可能 VS 的输出窗口已经显示了命令的绑定错误。尝试将 DataContext 定义放在首位(并自学为所有视图执行此操作)。

于 2011-01-27T07:38:10.577 回答
3

为了避免硬编码 KeyBindings,我派生了 Josh Smiths RelayCommand-Class并添加了与快捷方式相关的内容:

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}" />

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

于 2012-08-31T18:50:05.993 回答
0

我遇到了类似的情况,其中与键相关的事件仅在外壳视图中被收听,并且没有调整到按下键的实际视图。为了克服这个问题,我编写了一个小的附加行为来将焦点设置到用户控件或框架元素上,以便在初始加载时接收焦点,这样我想听的 UI 元素就会听到击键。

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

于 2012-05-31T20:05:39.983 回答
0

尝试这个:

<UserControl.InputBindings>
        <KeyBinding Key="C" Modifiers="Control" Command="{Binding CopyImageCommand}" />
        <KeyBinding Key="V" Modifiers="Control" Command="{Binding PasteImageCommand}" />
    </UserControl.InputBindings>
于 2014-01-22T09:34:13.717 回答
0

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

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

这应该有效。

于 2012-07-17T10:56:43.120 回答
0

你用的是3.5还是4?

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

它固定在4。

于 2010-10-15T10:42:04.353 回答
0

这个帖子太旧了,我会添加答案,也许有人需要答案可以在这个链接中找到

https://social.msdn.microsoft.com/Forums/vstudio/en-US/395046c8-2cc8-48b4-9642-341ce0c99cc9/key-binding-does-not-work-always-in-mvvm-application?forum= wpf

由于焦点问题,用户控件中的输入绑定应使用后面的用户控件代码分配给主窗口

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
        this.Loaded += UserControl1_Loaded;
    }

    void UserControl1_Loaded(object sender, RoutedEventArgs e)
    {
        Window window = Window.GetWindow(this);
        foreach (InputBinding ib in this.InputBindings)
        {
            window.InputBindings.Add(ib);
        }
    }
}
于 2022-01-12T21:11:27.207 回答