2010-10-15 108 views
9

我宣布<InputBindings>C#/ WPF:键绑定不触发命令

<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顺便说一句

UPDATE

更全面的代码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="*" /> 

UPDATE

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

+0

能否请您发布的InputBinding指定在哪里?可能你把它放在错误的地方。 – Euphoric 2010-10-15 11:00:39

+0

@Euphoric,我把我的InputBindings放在UserControl ShellView中。当我将它们放在MainWindow中时,我发现它可以工作,但我需要将视图模型设置为ShellViewModel,我认为这不是很正确,我该如何处理? – 2010-10-19 02:44:23

+1

@JiewMeng:你好!我有几乎相同的问题。你有没有找到解决办法? – Jalal 2012-03-26 21:22:54

回答

0

你使用3.5还是4?

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

其固定在4

+0

我正在使用.NET 4 – 2010-10-15 10:42:57

+0

我用一个更完整的代码snipplet更新了我的帖子,显示输入绑定的位置声明 – 2010-10-16 00:29:03

3

确保你没有绑定错误。您设置用户控件的DataContext,但确保这些命令可以绑定到它。有时候,WPF只是使用外观的顺序,DataContext会在稍后再设置命令。

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

0

我也有类似的情况在重点相关的事件都拿到在壳牌查看听过的,并没有tunelling到被按下的键的实际看法。 为了克服这个问题,我写了一个小的附加行为,将焦点设置到用户控件或框架元素收到的焦点初始负载和道路上的关键笔划由我要听的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

0

在这种情况下,你可以在你的RoutedCommand声明中提供的按键组合:

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

这应该工作。

4

为了避免硬编码的键绑定,我已经得出乔什史密斯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)); 
    } 
} 

然后在视图模型创建命令:

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

用这种方法我可以让用户调整在运行时的快捷键(在我的配置窗口)

+1

+1 ...优秀的解决方案!最后一个代码片段中的一个小错字:Modifiers =“{Binding NewFileCommand.Modifier}”应该是Modifiers =“{Binding NewFileCommand.Modifiers}”。 – 2014-10-14 17:18:43

0

试试这个:

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