7

I used CommandManager.RegisterClassInputBinding to add binding to the whole type. Now I want to remove it.

This is what I tested.

private void CommandBinding_Executed_1(object sender, ExecutedRoutedEventArgs e)
{
    CommandManager.RegisterClassInputBinding(
        typeof(TextBox),
        new InputBinding(TestCommand, new KeyGesture(Key.S, ModifierKeys.Control)));


    MessageBox.Show("CommandBinding_Executed_1");
}

This method is called on Ctrl+H and registers new input binding for Ctrl+S. If I press Ctrl+S before Ctrl+H it doesn't work, but when I press it after it does.

I checked sender.InputBindings and there was only one binding (Ctrl+S) so I concluded that RegisterClassInputBinding() doesn't add the binding to every existing instance but instead stores bindings associated to the class and then compares them to handled gesture.

But then why there is no RemoveClassInputBinding() method? :(

Edit


I even managed to do what I intended through reflection, but still can't find native method for that, though it would be trivial to implement.

var fieldInfo = typeof(CommandManager).GetField(
    "_classInputBindings", BindingFlags.Static | BindingFlags.NonPublic);
var fieldData = (HybridDictionary)fieldInfo.GetValue(null);
var inputBindingCollection = (InputBindingCollection)fieldData[typeof(TextBox)];
foreach (var o in inputBindingCollection)
{
    if (o == inputBinding)
    {
        MessageBox.Show("half way there");
    }
}
inputBindingCollection.Remove(inputBinding);
Tyress
  • 3,573
  • 2
  • 22
  • 45
Sergej Andrejev
  • 9,091
  • 11
  • 71
  • 108
  • Are you looking to implement key chords like in Visual Studio? If so, this may be helpful: http://kent-boogaart.com/blog/multikeygesture – CodeNaked Feb 26 '16 at 02:39

1 Answers1

8

ApplicationCommands.NotACommand was designed for just this purpose:

"This command is always ignored and does not handle the input event that caused it. This provides a way to turn off an input binding built into an existing control."

To use your example:

CommandManager.RegisterClassInputBinding(
    typeof(TextBox),
    new InputBinding(
        ApplicationCommands.NotACommand,
        new KeyGesture(Key.S, ModifierKeys.Control)));
user7116
  • 63,008
  • 17
  • 141
  • 172
  • looks very flawed to me. I'm writing shortcuts manager which would allow user to add/remove input bindings. As I understand if user removes a binding as you suggested the binding will be still there and it will accumulate everytime user does that. Is this correct? – Sergej Andrejev Jun 16 '09 at 09:16
  • That I do not know for sure, I'm just passing along the advice from Microsoft. I can tell you this much though, using Reflection is surely flawed. I'll go through Reflector and see if MS special cases NotACommand. – user7116 Jun 16 '09 at 13:23
  • CommandManager.TranslateInput (internal method) special cases to make sure NotACommand never gets executed: "if ((command != null) && (command != ApplicationCommands.NotACommand))". – user7116 Jun 16 '09 at 13:29
  • Aha, but still it's kinda odd they haven't allowed removing and sure enough using NotACommand leaves some garbage behind. – Sergej Andrejev Jun 16 '09 at 21:12
  • I agree, although I'm sure there is some other design consideration we are missing. – user7116 Jun 18 '09 at 19:15
  • It seems to me that the motivation behind not providing an `Unregister...()` method is that such class-level bindings are intended to be permanent. If your binding needs to come and go, it should probably be managed elsewhere. Alternatively, if it normally needs to be present, but in some specific context you want to disable it, then rather than doing the above (disabling it globally) you should create a `NotACommand` command binding _in that context_ (e.g. in a window's `InputBindings` collection). – Peter Duniho Feb 26 '16 at 02:07