2010-10-15 131 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>