The official Fatica Labs Blog! RSS 2.0
# Monday, May 02, 2011

Sometimes we want to use some shortcut key for special commands in our application, but the KeyBinding objects works with just routed commands, and so it is not directly usable with Caliburn Micro ( or with many other MVVM strategies ).
In similar situation CM rely on System.Windows.Interactivity.dll, for example when we need to map an event on a Caliburn action we can write:

 

 <Button x:Name="Save" >
           
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cl:ActionMessage MethodName="Save" ></cl:ActionMessage>
                </i:EventTrigger>
            </i:Interaction.Triggers>
 </Button>

 

With the code above, we explicitly link the "Click" event from the button to the action calling the metod Save. We can act in a similar way by creating a custom trigger, lets see how.
First look at what we can do it in XAML:

 

<i:Interaction.Triggers>
        <local:InputBindingTrigger>
            <local:InputBindingTrigger.InputBinding>
                <KeyBinding Modifiers="Ctrl" Key="S"/>
            </local:InputBindingTrigger.InputBinding>
            <cl:ActionMessage MethodName="Save"/>
        </local:InputBindingTrigger>
    </i:Interaction.Triggers>

 

We need to declare a class, deriving from TriggerBase in System.Windows.Interactivity in order to fire the action(s) in place of executing a routed command when the user press the proper key gesture. Here the code:

class InputBindingTrigger:TriggerBase<FrameworkElement>,ICommand
    {
        public InputBindingTrigger()
        {

        }
        public InputBinding InputBinding
        {
            get { return (InputBinding)GetValue(InputBindingProperty); }
            set { SetValue(InputBindingProperty, value); }
        }
        public static readonly DependencyProperty InputBindingProperty =
            DependencyProperty.Register("InputBinding", typeof(InputBinding)
            , typeof(InputBindingTrigger)
            , new UIPropertyMetadata(null));
        protected override void OnAttached()
        {
            if (InputBinding != null)
            {
                InputBinding.Command = this;
                AssociatedObject.InputBindings.Add(InputBinding);
            }
            base.OnAttached();
        }

        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            // action is anyway blocked by Caliburn at the invoke level
            return true;
        }
        public event EventHandler CanExecuteChanged = delegate { };

        public void Execute(object parameter)
        {
            InvokeActions(parameter);
        }

        #endregion
    }

 

Very easily we add the InputBinding to the bindings list on the object, and we attach the trigger as a command handler. In the execute function we fire the InvokeActions and it done. Please not the command on the KeyBinding is not required in the markup, since there is virtually any routed command.

Monday, May 02, 2011 2:16:17 PM (GMT Daylight Time, UTC+01:00)  #    Comments [8] - Trackback
Caliburn | Recipes | WPF

Thursday, September 08, 2011 9:14:10 AM (GMT Daylight Time, UTC+01:00)
Exactly what I was after, and worked perfectly...

Thanks loads!
Monday, October 31, 2011 2:24:03 PM (GMT Standard Time, UTC+00:00)
How can this be used in a ListBox?

I've tried several routes, but nothing seems to work. Either I get a runtime exception because of bad xaml or it simply doesn't call the method.
Henning
Monday, October 31, 2011 2:53:07 PM (GMT Standard Time, UTC+00:00)
@Henning you should describe better which error you are reciving. The method works even with ListBox ( ie it does not depend on the control you are using )
Felice Pollano
Monday, October 31, 2011 3:14:02 PM (GMT Standard Time, UTC+00:00)
Firstly I'm not sure where to put this piece of code.

I've created a simple gist that shows the xaml code for the item template and listbox
https://gist.github.com/1327688

The ContainerView.xaml hosts the Listbox control which in turn has an ItemTemplate that has a ContentControl which shows each item. The template for each item is specified in IndividualItem.xaml. It is all hooked up by CM and all its magic.

I've currently placed the trigger in the IndividualItem.xaml because that is where the method to be called lies (so to speak). I've also tried to place it in ContainerView.xaml but with no results. It doesn't fail but it doesn't call the method either.
The method signature is public void CopyKey()

Hope this explains it better.
Henning
Monday, October 31, 2011 3:34:54 PM (GMT Standard Time, UTC+00:00)
Difficult to say just by glacing at the code... but just to understand, can you attach the trigger to something that we can ensure has a focus ( add a textbox for instance ) and try if the trigger fires when this has the focus ? If so the problem is related to focus management that is what I guess.
Felice Pollano
Tuesday, November 01, 2011 11:47:38 AM (GMT Standard Time, UTC+00:00)
Yes, you're right. I added a TextBox and it was able to find and execute the method.

Now the question is how to fix this :p
Henning
Tuesday, November 01, 2011 12:47:56 PM (GMT Standard Time, UTC+00:00)
Well I do not have a solutionout-of-the box, but apparently stack overflow has :P http://stackoverflow.com/questions/1104601/xaml-how-to-have-global-inputbindings. It seems to be the key ( may be with some effort ) to solve your question.
Felice Pollano
Tuesday, November 01, 2011 12:48:19 PM (GMT Standard Time, UTC+00:00)
Well I do not have a solutionout-of-the box, but apparently stack overflow has :P http://stackoverflow.com/questions/1104601/xaml-how-to-have-global-inputbindings. It seems to be the key ( may be with some effort ) to solve your question.
Felice Pollano
All comments require the approval of the site owner before being displayed.
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, strike, strong) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview
My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2019
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 127
This blog visits
All Content © 2019, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano