I am trying to set the double click gesture of a text box in this way:
<TextBox>
<TextBox.InputBindings>
<MouseBinding Gesture="MouseDoubleClick" Command="{Binding DobleClickCommand}"/>
</TextBox.InputBindings>
</Textbox>
But I get the error that the mouse action MOUSEDOUBLECLICK is not allowed.
I would like to bind it to the command in my view model.
Is input bindings the way to do it?
Your mouse binding is wrong, there is no MouseDoubleClick, use LeftDoubleClick. For a list of valid mouse actions, look in the documentation. If you want to execute the action for MiddleDoubleClick or RightDoubleClick, too, you can create separate mouse bindings for them to the same command.
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding TestingCommand}"/>
Alternatively, you can use MouseAction instead of a Gesture:
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding DobleClickCommand}"/>
The documentation recommends to use Gesture instead of MouseAction:
When defining a MouseBinding in Extensible Application Markup Language (XAML), there are two ways to specify the MouseGesture. The first way to establish a MouseBinding in XAML is to define the Gesture attribute of the MouseBinding element, which enables a syntax to specify mouse actions and modifiers as a single string; for example, "CTRL+LeftClick". The second way is to define the MouseAction attribute of the MouseBinding element.
In general, it is recommended that you use only the Gesture attribute from XAML, even if you do not specify modifiers; this avoids ambiguity, provides the most streamlined syntax, and provides the most straightforward representation for serialization.
On the difference between a MouseAction and a Gesture:
A MouseGesture is a MouseAction with or without a set of ModifierKeys. Unlike a KeyGesture, a MouseGesture does not need to have a modifier key associated with it.
Related
I have a UI with a few controls.
Initially when form loads, search button will be disabled, once all
search criteria are given, search button will be enabled
automatically.
On click on search button, I want to call the method
using MVVM pattern and bind the result in grid
XAML:
<Button Name="btnGetDetails" Content="Get Details" Grid.Row="2" Command="{Binding SearchCommand}"/>
What code is required in model, view model and XAML?
Command will be executed only when the button will be clicked on. If you need to do something to the button then you should do it to the Window that contains the button (assuming your button is in a Window). Now if you want to stick with the MVVM pattern then you should not use the Window.OnLoaded, because that would put code in your code behind. One option is to use System.Windows.Interactivity, which you have download seperately. Here is what it will look like:
<Window x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr
-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding ...}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Window>
As for what your Model, View and ViewModel should be, I think you should check out some tutorials on the web. There are some very good explanations on how to implement the MVVM pattern. I found this youtube video pretty informative myself:
http://www.youtube.com/watch?v=EpGvqVtSYjs
So some MVVM basics here. You're on the right track, just missing a step. Your Command implementation in your view model should (potentially) accept two inputs: An Action representing the executing code, and a Predicate that returns true/false on whether you can execute the code in the Action block. So, in your view model, define your command along the lines of (note: this is a sample from one of my projects):
this.executeCommand = new RelayCommand(this.OnExecuteClicked, this.OnCanExecuteChanged);
The OnCanExecuteChanged method will return a bool based on whatever criteria you set up. So, if you want the submit button enabled when property A and property B have been properly set up, then return true, else return false. The internal workings of your command implementation will take care of the rest. Do a search for a RelayCommand implementation (if you don't have it already) or a DelegateCommand for further samples.
I have a WPF/MVVM app with a ListBox which displays data through a DataTemplate. I managed to change the selected item in the ListBox when pressing a button so the CommandParameter is linked to the ListBox's SelectedItem, but I cannot get the buttons to be enabled/disabled correctly in the same way. For example, if I have 2 items and the button should be enabled in one and disabled in the other, when I select an element BOTH buttons have the same state, and they BOTH change state when I select another item.
I am using a RelayCommand as used in many MVVM Frameworks.
Here is my XAML (removed "not interesting" parts):
<UserControl.Resources>
<DataTemplate x:Key="ItemTemplate">
<Grid>
<Button Content="Something" Name="EnabledDisabledButton" Click="Button_Click"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SomeCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItem}"/>
</Grid>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
</Style>
</UserControl.Resources>
<ListBox x:Name="myListBox" ItemsSource="{Binding ElementList}"
IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ContainerStyle}"/>
I tried to pass the SelectedItem as a parameter to the RelayCommand's CanExecute method, but the result was the same as before.
Is there a way to pass the actual ListBoxItem in which the button "lives in" as a parameter to the command, so each one will be processed separately by the CanExecute method? Would it work if I got this? (right now I am handling the Click event to select the correct item in the list before executing the command).
In my CanExecute method I am evaluating some property of the SelectedItem in order to enable/disable the corresponding button. An alternative would be to evaluate this property for all elements, but I cannot think of a way to do it inside the ViewModel, and then communicate to the view the result (if it is even possible while using a DataTemplate for the items).
Thanks for your input, regards!
Converting My comment into an answer:
Why not just CommandParameter="{Binding}"?
You mention "MVVM" in the question, but it seems you use the MVVM way to your full advantage.
I would not have a Button_Click event in the style at all. That is because it is in fact a style, which per definition could be changed to another style which does not have the same event, which again will make the application stop working as wanted if you choose to have a style-based app in the future.
A rule I use is that a style is a style. A style has to do with the UI and "looks" of the app.
Functionality should be separate from the UI. The programmer can define the Command, and the designer can decide how the user will use that in the best way.
That's exactly where the code separation from the MVVM pattern cames into grip.
To separate the "looks" and user behavior and the app's logic.
Like...it should not matter to the model if a command fires from a button, a menu, a datacontext or a key stroke.
If this particular problem was handled to ME, I would solve it by having a HOLDER-class.
This is a class (DependencyObject which implements INotifyPropertyChanged) that holds a ICommand property as well as the "row" that will be displayed in the various rows in the ListBox.
The ICommand property will be bound to the Button, having the row (class) itself as CommandParameter to the call.
Then the actual row would be used in the ItemTemplate on the ListBox, with Bindings to different elements (proprty with or withouy Converters) to make whatever desired display available.
I hope I explained good enough...
Feel free to ask more if you want more details to my solution alternative.
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.
I have a custom command and I try to execute them from the context menu, but they are always displayed as disabled unless I click any button on the UI (buttons do not have anything to do with commands).
After clicking a button, commands start to be displayed correctly (when they are unavailable they get disabled and enabled if available).
Edit: it turns out that it is not the button click which makes command work correctly, but button or other controls in focus (e.g. if I tab into a control this also enables my commands).
Here is the code for commands:
<Window.InputBindings>
<KeyBinding Command="{x:Static local:MainWindow.Quit}" Key="Q" Modifiers="Ctrl"/>
<KeyBinding Command="{x:Static local:MainWindow.Disconnect}" Key="D" Modifiers="Ctrl"/>
</Window.InputBindings>
<Window.ContextMenu>
<ContextMenu Opacity="95">
<MenuItem Header="Quit Application Ctrl + Q" Command="{x:Static local:MainWindow.Quit}"/>
<MenuItem Header="Disconnect from the pump Ctrl + D" Command="{x:Static local:MainWindow.Disconnect}"/>
</ContextMenu>
</Window.ContextMenu>
Here is the commands CanExecuteMethod:
public static RoutedCommand Quit = new RoutedCommand();
private void QuitCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
This issue is due to the ContextMenu being on a separate Visual and Logical Tree to that of the Window and its Controls.
For anyone still looking for an answer to this issue - After trawling the internet I have found the most effective answer to be to include the following in any declaration of a MenuItem that needs its commands to be heard by it's "owner".
In layman's terms; if you want the commands of your context menu to be heard by the thing you're right clicking on. Add this code:
CommandTarget="{Binding Path=PlacementTarget,
RelativeSource={RelativeSource AncestorType=ContextMenu}
}"
Example:
<ContextMenu>
<MenuItem Header="Close" Command="Application.Close"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
</ContextMenu>
This will also work within Templates (something I found a lot of another solutions not to support). Here is an explanation of the meaning of the statement taken from elsewhere (I'm appalling at explaining things):
Every FrameworkElement has a DataContext that is an arbitrary object. The default source for a data binding is that DataContext. You can use RelativeSource.Self to change the source for a binding to the FrameworkElement itself instead of its DataContext. So the RelativeSource part just moves you "up one level" from the DataContext of the FrameworkElement to the FrameworkElement itself. Once you are at the FrameworkElement you can specify a path to any of its properties. If the FrameworkElement is a Popup, it will have a PlacementTarget property that is the other FrameworkElement that the Popup is positioned relative to.
In short, if you have a Popup placed relative to a TextBox for example, that expression sets the DataContext of the Popup to the TextBox and as a result {Binding Text} somewhere in the body of the Popup would bind to the text of the TextBox.
I honestly hope that this information saves someone who's new to WPF the headache I've gone through this weekend... though it did teach me a lot!
Completely different track, now:
there is indeed something special about the ContextMenu as the carrier for commands:
the menu is not regarded as part of the window and therefore does not behave like an element in its visual tree would.
There are different solutions for your problems defined here:
http://www.wpftutorial.net/RoutedCommandsInContextMenu.html
The easiest approach seems to be adding this to your XAML (for the window):
FocusManager.FocusedElement="{Binding RelativeSource={x:Static RelativeSource.Self}, Mode=OneTime}"
I just ran into this while trying to implement a custom context menu for AvalonDock. None of the solutions suggested above worked for me.
I got the context menu working by explicitly registering my command handlers on the ContextMenu class in addition to the main widow. The function below is a helper I used for command registration.
void RegisterCmd(RoutedCommand command, ExecutedRoutedEventHandler handler, CanExecuteRoutedEventHandler canExecute)
{
var binding = new CommandBinding(command, handler, canExecute);
this.CommandBindings.Add(binding);
CommandManager.RegisterClassCommandBinding(typeof(ContextMenu), binding);
}
There is probably some change "behind the scenes" that would normally enable the commands, but the view is not aware of this change.
One would need to see the Command-implementations to give more precise hints.
You can either make anything that changes your command-enable-state notify the view or manually trigger a command-refresh via CommandManager.InvalidateRequerySuggested(), for example when the context-menu opens.
WPF ICommands work that way; they requery their CanExecute function whenever something in the view changes (e.g. PropertyChanged-event is fired or a button is clicked), but they don't requery if they have no reason to.
This is a known bug. If there is no focused element in the window's main focus scope, the CanExecute routing will stop at the ContextMenu, so it will not reach to the CommandBinding on the Window, one workaround is to bind MenuItem's CommandTarget to the main window, as following code demonstrates:
<Window.ContextMenu>
<ContextMenu >
<ContextMenu.Items>
<MenuItem Command="ApplicationCommands.Open"
CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu.Items>
</ContextMenu>
</Window.ContextMenu>
I have a custom Control derived class and a view model to go with. The user can do several actions with this control, and I'm thinking it's best to implement these as RoutedCommand objects or ICommand derived objects in the view model so the ControlTemplates can bind to them. Binding a command to a button in one ControlTemplate should be straightforward, but how can I bind the command to e.g. the right mouse button in another ControlTemplate? Probably a MouseGesture is involved, but I'm having a hard time fitting the pieces together.
A MouseGesture is involved, but you don't have to explicitly construct it. You can use a MouseBinding which will construct a MouseGesture for you under the hood.
You need a UIElement to attach your binding to. Here is how you would do it with a separate decorator.
<ControlTemplate ...>
<Decorator>
<Decorator.InputBindings>
<MouseBinding MouseAction="RightClick" Command="..." />
</Decorator.InputBindings>
... content here ...
</Decorator>
</ControlTemplate>
More likely your ControlTemplate uses a Panel such as a DockPanel or Grid for layout, in which case you could attach the binding to that instead of adding a Decorator.