2010-10-15 24 views
9

I zadeklarowały <InputBindings>C#/WPF: nie kombinacja klawiszy uruchamiania poleceń

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

Dla celów testowych Dodałem przyciski związane z tymi poleceniami zbyt

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

Zauważyłem, że po naciśnięciu przycisku pasta jest włączone, kiedy naciśniesz Ctrl-V nic się nie dzieje. Ctrl-C wydaje się działać. W tym celu wybrano element listy, nie jestem pewien, czy to robi jakąkolwiek różnicę. Ktoś wie, dlaczego mój PasteImageCommand nie uruchamia się?

Używam .NET 4 btw

UPDATE

Kod pełniejsze 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

I okazało się, że trzeba umieścić KeyBindings w MainWindow, ale polecenia są w ViewModel, w jaki sposób ustawić powiązania klawiszy w ShellView, które następnie wiąże się z poleceniami w ShellViewModel?

+0

Czy należy zakładać, gdzie są InputBinding podanej? Możliwe, że umieścisz go w niewłaściwym miejscu. – Euphoric

+0

@ Euforyczne, umieściłem moje InputBindings w UserControl ShellView. Odkryłem, że działa, gdy umieściłem je w MainWindow, ale muszę ustawić model widoku na ShellViewModel, nie bardzo poprawne myślę, jak mogę sobie z tym poradzić? –

+1

@JiewMeng: Hi jiew! Mam prawie ten sam problem. znalazłeś jakieś rozwiązanie? – Jalal

Odpowiedz

0

Czy używasz 3.5 lub 4?

W 3.5 jego "funkcja". UserControl.InputBindings nie jest częścią drzewa dataContext, więc nie można powiązać z elementami klasy związanymi z rodzicem. na przykład. DataBinding nie działa i musisz ustawić DataBinding lub całe KeyBinding w kodzie ręcznie.

Jego trwałe w 4.

+0

Używam .NET 4 –

+0

Zaktualizowałem mój post z pełniejszym fragmentem kodu pokazujący, gdzie są powiązania wejściowe zadeklarowany –

3

Upewnij się, że nie mają wiążących błędów. Ustawiasz DataContext formantu użytkownika, ale upewnij się, że polecenia mogą się z nim wiązać. Czasami WPF po prostu używa kolejności pojawiania się, a DataContext jest ustawiany później niż polecenia.

Prawdopodobnie okno wyjściowe VS pokazuje już błędy wiązania dla poleceń. Spróbuj umieścić definicję DataContext na wierzchu (i naucz się robić to dla wszystkich widoków).

0

Miałem podobną sytuację, w której w wydarzeniach związanych z kluczem słuchano tylko w widoku powłoki i nie dostosowywano do rzeczywistego widoku, w którym naciśnięto klawisz. Aby rozwiązać ten problem, napisałem małe załączone zachowanie, aby ustawić fokus na element sterujący użytkownika lub element struktury, aby uzyskać skupienie na początkowym załadowaniu iw ten sposób suwaki klawiszy są odsłuchiwane przez element interfejsu, którego chcę słuchać.

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

i wykorzystał je w ten sposób w jednym z moich poglądów lista poniżej -

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

nadzieję, że to pomaga.

-VJ

0

W tym przypadku można zapewnić skróty klawiszowe w swojej deklaracji RoutedCommand:

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

to powinno działać.

4

Aby uniknąć jawnie wpisanej skróty klawiszowe, mam pochodzi Josh Smiths RelayCommand-Class i dodaje skrót związanego rzeczy:

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

następnie utworzyć polecenia w 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; 
} 

i wiązania go w widoku :

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

Dzięki temu podejściu mogę zezwolić użytkownikowi na dostosowanie skróty w czasie pracy (w moim oknie konfiguracyjnym-)

+1

+1 ... Doskonałe rozwiązanie! Jedna drobna literówka w ostatnim fragmencie kodu: Modyfikatory = "{Binding NewFileCommand.Modifier}" powinny być modyfikatorami = "{Binding NewFileCommand.Modifiers}". –

0

Spróbuj tego:

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