I have a tabbed GUI with each tab containing a Frame. I use the EventToCommand with the SelectionChangedEvent whenever a new TabItem is selected. I do this to update the state of the app. This all works fine - a little bit too fine, the event gets fired too often. Here is my problem:
How can I prevent the event from bubbling up the visual tree by setting the Handled property on the event when using the mvvm light eventToCommand feature?
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<mvvm:EventToCommand
Command="{Binding YourCommand}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Your command needs to provide parameter from method like RelayCommand . This parameter is event args providing Handled property. More here.
Related
I wanted to handle MainWindow's Closing event in one of my ViewModel. This ViewModel belongs to a View which is displayed on top of the MainWindow. I wanted to save values of some properties present in that ViewModel while/before closing of the application.
I am using MvvmCross to implement MVVM pattern. So I tried overriding ViewDisappearing, ViewDisappeared and ViewDestroy methods, but they are only getting called when View get switched, but not when application/window closes.
While searching for this requirement, I could only find this answer: https://social.msdn.microsoft.com/Forums/vstudio/en-US/477e7e74-ccbf-4498-8ab9-ca2f3b836597/how-to-know-when-a-wpf-usercontrol-is-closing?forum=wpf , which is close to my requirement, but needs to be implemented in code-behind.
Can anyone please help me in achieving this in MVVM/MvvmCross in WPF?
I had some experience to implement events by MVVM maybe it can help you.
As I know there is a package on Microsoft.Xaml.Behaviors.Wpf that will help to get the events and execute a command
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding ClosingWindow}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
and if you want to execute a command in other view models you can use a static command
xmlns:local="clr-namespace:App.Views.Windows"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{x:static local:ViewModel.ClosingWindow}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I'm trying to handle the window closing using a solution similar to this, but the handler in my ViewModel is firing on application start, and not when closing.
XAML:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<command:EventToCommand Command="{Binding WindowClosing}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
ViewModel:
public RelayCommand<System.ComponentModel.CancelEventArgs> WindowClosing
{
get
{
return new RelayCommand<System.ComponentModel.CancelEventArgs>((args) => {});
}
}
The binding is obviously functioning, but it's just firing at exactly the wrong time. I thought the EventName="Closing" is what was supposed to bind to the actual closing event, but it doesn't matter what's contained there. It always fires on loading. What exactly is supposed to link this to the actual window closing event?
I'm little confused about RelayCommand and EventToCommand in Mvvmlight.
It seems that EventToCommand handle the EventTrigger and call a RelayCommand to do job.
Such as:
<i:Interaction.Triggers>
<i:EventTrigger x:Uid="i:EventTrigger_1" EventName="MouseLeftButtonUp">
<cmd:EventToCommand x:Uid="cmd:EventToCommand_1" Command="{Binding Form_MouseLeftButtonUpCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Is my understanding correct?
So, can we use RelayCommand directly with EventTrigger, no need to use EventToCommand?
Thanks for your help!
EventToCommand is a custom behavior. It is first provided by Expression blend team and now Part of WPF 4. If you're not using WPF4. you require Blend SDK from here.
Behaviors encapsulates functionality as reusable components. These are to be used when feature is not present by default. For example Adding Command support to Label, Combobox etc.
can we use RelayCommand directly with EventTrigger, no need to use EventToCommand?
No. RelayCommand is a shortcut to avoid code redudnency to define custom commands.It extends ICommand whose delegates can be attached for Execute(T) and CanExecute(T). It is similar to DelegateCommand of Prism library.
<cmd:EventToCommand x:Uid="cmd:EventToCommand_1" Command="{Binding Form_MouseLeftButtonUpCommand}" PassEventArgsToCommand="True"/>
In above line cmd:EventToCommand is additional feature to the underlying control. Form_MouseLeftButtonUpCommand is the Command it executes. This command can be encapsulated as RelayCommand.
Thank Tilak for your useful answer.
With the explanation from Tilak, I did mess up like putting a binding in a event handler (such as Button GotFocus="{Binding DoJob}") --> Build failed and found that Event Handler like this does not support Binding. We can only bind in Command (such as Button Command="{Binding DoJob}" /> and default event is invoked in this situation, with button, it should be Click event).
Do something stupid will help me to understand the life more - LOL
can we use RelayCommand directly with EventTrigger, no need to use
EventToCommand?
Actually, I intend NOT to use EventToCommand, and I found the solution for that: use InvokeCommandAction instead (belongs to System.Windows.Interactivity - Mvvm-light also refers to this assembly).
I have a view containing a button. And i want to perform an action on Hold event. How can i do this in mvvm? For Tap event i can Bind it to a Command property. Is it possible to do this with same way?
I would go with Braulio's answer - MVVM Light is what I would use, but back in the Silverlight 3 days I used custom attached properties to achieve this. See here for an example of custom attached properties: http://umairsaeed.com/2010/04/22/custom-attached-properties-in-silverlight/
You could create a custom attached property for the hold event to bind the command to and then use it like so:
<Border local:MyTextBoxControl.HoldEventCommand="{Binding HoldCommand}"/>
This is a lot of work compared with including the mvvm light toolkit in your project and then doing this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Hold">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding YourCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Not sure if it supports the command, if not you can use MVVM Light Toolkit (free and open source) behavior: EventToCommand
I am currently transforming a medium size WPF project to MVVM and I ran into a problem that I wasn't able to solve, yet. Maybe you could help me out?
The target framework is .NET 3.5.1.
I have a list view that gets its items from the underlying view model. That view model is exposing a command to remove the selected items from the list view. Therefore the command parameter is bound to the SelectedItems property of the list view.
<ListView ItemsSource="{Binding MyItems}"
x:Name="MyListView"
SelectionMode="Extended">
</ListView>
<Button x:Name="MyRemoveButton"
Content="Remove item"
Command="{Binding RemoveItemCommand}"
CommandParameter="{Binding ElementName=MyListView, Path=SelectedItems}">
My intention is to execute this command not only when pressing a button, but also when the KeyUp event is fired on the list view and the pressed key is "delete".
I was close to finding the solution when I stumbled upon interaction triggers in this example:
http://joyfulwpf.blogspot.com/2009/05/mvvm-invoking-command-on-attached-event.html?showComment=1250325648481#c3867495357686026904
Now the problem with this demo is that the command parameter is the pressed key, but in my case I need the command parameter to be the SelectedItems property and I need the command to execute only on a specific key.
Is there any way to do this without much overhead and in the MVVM way?
Something like this would be awesome:
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<local:CommandAction Command="{Binding RemoveItemCommand}"
CommandParameter={Binding ElementName=MyListView, Path=SelectedItems}
EventArgument="Key.Delete"/>
</i:EventTrigger>
</i:Interaction.Triggers>
To do it in the MVVM way you need to bind "SelectedItems" property of the ListView to your ViewModel, so you could use it from your commands and wouldn't need to pass it via CommandParameter.
How strict is your separation requirement? If you don't have designers using Blend, then put a call to a ViewModel method into the KeyUp or PreviewKeyUp event handler in your code-behind.