MVVM Pass key as CommandParameter in KeyBinding of Window - wpf

Is there a way to pass entered key as command parameter in InputBindings of Window? I tried achive this by code below, but it isn't working.
<KeyBinding x:Name="KeyBinding" Command="{Binding ChoosePackageSizeFromKeyboard}" CommandParameter="{Binding ElementName=KeyBinding, Path=Key}" />
I don't wanna create binding for every key I wanna use, cause depending of condition it will be beetween 1 and 5 keys. Any ideas how to pass it to command?

I don't think it's possible to use KeyBinding the way you want to. You have to provide a value for the Key property for it to work.
What you could do instead is handle the KeyUp (or similar) event on the Window. If you want to bind on a Command, you can take a look at this SO answer for more details on how to pass the EventArgs to the command.

Related

Invoking WPF command on IntegerUpDown (Extended WPF Toolkit)

I am using mvvm pattern and using integerupdown button in the WPF application.
To invoke command currently I am using ValueChanged trigger as following -
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding PercentChangedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
This works perfectly fine when user changes value using mouse click on up or down arrow.
Problem is the moment user wants to type in textbox, the event get triggered for every character typed in. Instead I want to allow user to type in numbers and trigger command only on hitting Enter.
Please suggest.
if ValueChanged is triggered on every KeyStroke then your Bindings UpdateSourceTrigger is likely set to default (ValueChanged). Start by setting it to LostFocus. Additionally catch the KeyDown-event with an EventTrigger and check if the key pressed was the Enter-Key.
If its the enter-key then simply call your command.
Edit: if you need a reusable solution for Commit-On-Enter-scenarios have a look at this question.
Found a property - UpdateValueOnEnterKey="True". This will not invoke value changed on every character change, but only on Enterkey press

How can I invoke relay command with parameter programmatically wpf mvvm?

I know how to invoke relay command without parameter using mvvm pattern, but how to do the same with command with parameter?
https://i.stack.imgur.com/o7r5i.jpg
https://i.stack.imgur.com/zNkYR.jpg
https://i.stack.imgur.com/lmw3w.jpg
https://i.stack.imgur.com/iJnF0.jpg
If I understand you correctly, your command requires you to pass the TextEditor object in as a parameter, and you'd like to know how to do this in XAML. Since your TextEditor is named XMLView you'd simply bind this to the command parameter;
<KeyBinding Command="{Binding ValidateXMLCommand}" CommandParameter="{Binding ElementName=XMLView}" Modifiers="Control" Key="V" />
Notice the addition of CommandParameter="{Binding ElementName=XMLView}", this will pass the AvalonEdit TextEditor control instance as a parameter of the command.
Read more; https://stackoverflow.com/a/32064646/8520655
If you instead mean to invoke the RelayCommand from a ViewModel (in normal C#), you'd do the following;
if (ValidateXMLCommand.CanExecute(XMLView))
ValidateXMLCommand.Execute(XMLView);
Also, please do not post images of code, but rather your code formatted using the code style.
The control (e.g. Button / MenuItem) that you're binding your relaycommand to will have a CommandParameter property in addition to the Command property.
See here for an example of usage.
To execute a command from code behind, just call its Invoke() method, with the required parameter.

How to automatically get hotkey on a WPF tooltip?

In my window, I have this:
<UIElement.InputBindings>
<KeyBinding Gesture="Ctrl+Left" Command="{Binding MoveTaskCommand}" CommandParameter="{x:Static plugin:MoveDirection.Left}"/>
...
And down in the tree, I have this:
<Button HorizontalAlignment="Left"
ToolTip="Promote to Parent Level (Ctrl+Left)" Command="{Binding MoveTaskCommand}"
CommandParameter="{x:Static plugin:MoveDirection.Left}">
...
I don't like the redundancy, and I don't like copy pasting my hotkey's "Ctrl+Left" into the tooltip. I'm 99% certain WPF has a better way of doing it than this.
Could someone point me in the right direction?
Could someone point me in the right direction?
Option 1: I would try using a custom Attached Property maybe "IsToolTipGesture". In the PropertyChangedCallback, check if there's a ToolTip and any UIElement.InputBindings. If there are, update the ToolTip with the appropriate information from the InputBindings.
Option 2: Another thing to try if you want this behavior on ALL elements below a certain root is using a similar approach with an attached property and recursively checking child elements (via VisualTreeHelper) to see if they have a ToolTip and any InputBindings.

ProcessCmdKey analog in WPF

I'm new to WPF and in WinForms to add hotkeys to the form I've usually used ProcessCmdKey that made easy to override(add) key related functionality (similar to the way described here). Is there an easy way to assign hotkeys in WPF? I'm using Commands with keys, but sometimes that doesn't work (I think some other controls on window respond to that gestures and do their jobs, so that my command can't respond to predefined key gesture).
InputBindings are scoped with the control they are assigned to, if you assign a KeyBinding in the Window.InputBindings they will be fired throughout the window unless the same gesture is locally overridden by being defined somewhere down the tree.
For example this:
<UserControl.InputBindings>
<KeyBinding Gesture="CTRL+SHIFT+N"
Command="{Binding BtnNewChild_Command}"
CommandParameter="{Binding ElementName=view}" />
</UserControl.InputBindings>
doesnt work, it cant pass the view element as parameter, tho there is control named "view" in that UserControl. Does wpf have some "common" hotkey assign scenario?
The problem here would just be scope, the child controls have access to things declared higher up on the tree but not the other way around. You could possibly refactor this to create your view as a resource in the UserControl.Resources then you can reference it both in the CommandParameter and whereever you use it in the UserControl.

WPF MVVM: Find out on which header context menu has been clicked

I am trying to use the MVVM pattern to write a WPF application. I am using WPF data grid (from the toolkit) which lacks the autofiltering feature. So I want to implement it. I've added a context menu to the column header template, it has MenuItem called "Filter" which should actually call the filtering method.
So I've set a MenuItem's command to be the appropriate DelegateCommand which goes to the ViewModel. The problem is that I need to pass the information about the actual column that has been right-clicked! If I wasn't using MVVM, I would implement an event handler which would receive a "sender" argument (the MenuItem), then I would find its parent (the ContextMenu), then its parent would give me the column. But how can I achieve the same thing here? How can I pass the sender to my command? Can this be done using ComandParameter?
I really don't want to use additional complicated patterns to achieve such a simple task. After all, MVVM should simplify the development and not vice versa...
Can you pass the Column header value as a Command Parameter and use that to get the Column details at the ViewModel?
You could try some relative source magic, but it might be easier on you if you can have a different ViewModel that you bind to for each header, like HeaderViewModelItem. From there you'd just be firing a DelegateCommand in your HeaderViewModelItem, rather on your larger viewmodel.
I've used this model with pretty good success. Gets around a little bit of databinding dance.
If you want to pass something into the command parameter it is important to note that a context menu is on its own visual tree. Luckily it still inherits the DataContext from its parent, so something like
<MenuItem CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}" />
should get you the GridViewColumnHeader, or at least something in the visual tree of it.

Resources