Handling Mouse events on controls with MVVM pattern - best practice - - wpf

I found actually 2 ways to handle mouse events on controls with the mvvm pattern.
Both ways are actually 1 way:
MVVM Light Toolkit by http://mvvmlight.codeplex.com/
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand
Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding SelectedItems,
ElementName=MyDataGrid}" />
</i:EventTrigger>
</i:Interaction.Triggers>
and the Blend interactivity.dll with Behaviours
<i:Interaction.Triggers>
<i:EventTrigger EventName=”MouseLeftButtonDown”>
<Behaviours:ExecuteCommandAction Command=”{Binding MyCommand}” CommandParameter=”{Binding MyCommandParameter}”/>
</i:EventTrigger>
</i:Interaction.Triggers>
Do you know of any better method?
Moderator: Why the heck are my last 6 xaml lines of code not visible at all?
They are swallowed by IE and Iron browser.
Would you please report the admin to fix that code script? its not working at all very often. prove: http://img251.imageshack.us/img251/5236/errorxt.png

Those are both good ways to do it if you need to handle MouseDown in arbitrary places.
However these situations generally are few and far between. Usually there is a simpler way:
Are you sure your objects aren't really buttons that just don't look like buttons? If so, make them real Button objects and template them to look the way you want.
Are you sure your objects are just selection areas for objects in a list? If so, change the container from ItemsControl to ListBox and restyle ListBoxItem to use the selection areas.
Are your objects graphical paths that are being selected? Use a ToggleButton whose content is the path itself.
There are many other examples of this. In fact, it is uncommon to find a situation in which a MouseDown maps to a Command and there isn't a cleaner way to do the same thing.

There is always another option. You can handle WPF events in the code-behind of the View and call the appropriate method on the ViewModel. The MVVM pattern doesn't forbid to write any code in the code-behind file of the View.
The ViewModel sample application of the WPF Application Framework (WAF) shows how this can work.

XCommand Open source codeplex project has better way to deal with this event based Command/CommandParameter binding. Find here, xcommand.codeplex.com
Here is the sample code below:
<Grid>
<TextBlock Margin="20,30,20,0" VerticalAlignment="Top" Height="80" x:Name="XTextBlock"
Foreground="{Binding FgColor, Mode=TwoWay}"
XCmd:MouseMove.Command="{Binding TextBlockPointerMovedCommand}"
XCmd:MouseLeftButtonDown.Command="{Binding TextBlockPointerPressedCommand}"
XCmd:MouseLeave.Command="{Binding TextBlockPointerExitedCommand}"
Text="{Binding Description, Mode=TwoWay}">
</TextBlock>
<Grid Grid.Column="1" Background="{Binding BgColor, Mode=TwoWay}"
XCmd:MouseMove.Command="{Binding GridPointerMovedCommand}"
XCmd:MouseMove.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
XCmd:MouseLeftButtonDown.Command="{Binding GridPointerPressedCommand}"
XCmd:MouseLeftButtonDown.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
>
</Grid>
</Grid>
Hope this will be helpful.

Related

ComboBox's SelectionChanged inside datagrid not firing mvvm

I am using MvvmLight toolkit for my event interactions, i have tried many solutions available but none worked. The combo box inside my data grid's Selection Changed event is not firing
Here is my xaml:
i used both InvokeCommandAction and EventToCommand:
EventToCommand Command="{Binding rlcCbSelectionChanged, Mode=OneWay}"
PassEventArgsToCommand="True"
InvokeCommandAction Command="{Binding rlcCbSelectionChanged, Mode=OneWay}"
Please tell me what am i missing??
Selection Changed event successfully fires on data grid with same procedure given above.
Well answer is quite simple i was missing an attribute that is optional that is why i leave this one previously but that causes selection change event not to fire. So i add my view model key as a static resource and it worked :)
So my working xaml look like :
<i:EventTrigger EventName="SelectionChanged">
<i1:InvokeCommandAction Command="{Binding Path=rlcCbSelectionChanged, Source={StaticResource dvm}}"/>
</i:EventTrigger>

Best way to create a list of selectable and deletable items in Windows Phone 7

I want to solve a seemingly simple task. I want to create a list of text entries where each entry is selectable (and causes navigation to another page) and when the user holds his finger over an item I want a context menu with a single option to delete that item. This is very common pattern in WP applications. For example the browser does this with favourites.
Right now I have a listbox with a textblock in the item template and I start the navigation in the SelectionChanged event:
<ListBox Name="lbSnippets" SelectionChanged="lbSnippets_SelectionChanged">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
I can think of several ways to solve the hold problem but none of them sits well with me. For example I may handle the Hold event on the TextBlock but then I will have to dig for the item related to this TextBlock. Something tells me that there should be a better way to do this as it is so common. What is the right way to solve this task?
The Silverlight toolkit for WP7 includes a ContextMenu control.
You can install the toolkit via nuget: PM> Install-Package SilverlightToolkitWP
Then you an add ContextMenus to basically any control:
<DataTemplate>
<TextBlock Text="{Binding}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Delete"
Command="{Binding YourDeleteCommand}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</DataTemplate>
Where toolkit is an xml namespace:
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
You can start learning about the ContextMenu control from this article:
WP7 ContextMenu in depth | Part1: key concepts and API

What ways are there for handling a double click event without using codebehind?

I saw an article detailing how to do this using attached behaviors which I like a lot. However, the download doesn't work and the article is pretty old (a couple of years).
What is the current way for handling events like this without using codebehind? Are there any that are MVVM-specific?
You can use the expression blend extensions:
<ListBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="CommandNameHere"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
It is another dependency, but it does seem to work well in .NET 4.
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=10801
Edit: You can also use the CommandParameter To Pass In Extra Things (Like The Selected Item View Model)

How can I bind an Event to changing the property on another element in the tree in XAML WPF?

I'll start off with the code as it should be fairly self-explanatory:
<commonControls:SearchTextBox
x:Name="searchTextBox"
Margin="6,0"
HorizontalAlignment="Right"
MinWidth="50"
Width="130"
SearchMode="Instant"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Search">
<cmd:EventToCommand Command="{Binding Search}"
CommandParameter="{Binding ElementName=searchTextBox, Path=Text}" />
</i:EventTrigger>
<i:EventTrigger EventName="Cancel">
<!-- Code to set searchTextBox.Text to Empty -->
</i:EventTrigger>
</i:Interaction.Triggers>
</commonControls:SearchTextBox>
The SearchTextBox has an Event called Cancel which executes if the user clicks the X button on the right hand side of the TextBox. What I would like to do is hook onto that event, and clear the Text property of the TextBox. I'm looking for a way to do this purely in XAML, with no Code Behind, and without hitting the ViewModel.
You can achieve this using a concept called 'attached behaviours', attached properties that on attachment handle events on the target object and perform some action as a result. See the following article:
http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx
I see you are already using blend interactions. Blend provides a simple framework for behaviours making them easier to implement, you simple override the OnAttach method to add your logic. See the example here:
http://www.scottlogic.co.uk/blog/colin/2011/06/metro-in-motion-part-7-panorama-prettiness-and-opacity/

WPF: CommandParameters for input bindings

One of the things I really like with WPF is the extent to which my views can be built declaratively, ie. using XAML rather than code-behind.
Now I'm really stumped by InputBindings, because their CommandParameters don't accept bindings. I imagine my case is pretty generic and straightforward, but I cannot see how I can do it without resorting to code-behind. Consider:
<ListBox Name="casingsListBox" ItemsSource="{Binding Path=Casings}" SelectedValuePath="Id">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Title}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.InputBindings>
<!-- Doesn't work: -->
<MouseBinding Gesture="LeftDoubleClick"
Command="ApplicationCommands.Open"
CommandParameter="{Binding RelativeSource={RelativeSource Self} Path=SelectedValue}"/>
</ListBox.InputBindings>
</ListBox>
This will not work, since the binding expression for the MouseBinding's CommandParameter is illegal.
I ask myself: what's the point of adding a mouse-click gesture to a listbox if I cannot get to the selected value?
This can be easily solved using a code-behind event handler, of course, or by having the command consumer extract the id from the command source, but there are several reasons why this is undesirable. Apart from the fact that droves of code-behind code defeats (some of) the purpose of WPF in the first place, it makes the UI designers working in Expression Blend less empowered. And dammit, my command parameter shall be an id, not some UI element!!
Subjective: Having browsed SO for a while, I'm struck by the amount of code I see in the WPF-related questions. I get the feeling we developers stick to our old habits and happily hack away in the code-behind file rather than trying to utilize the fresh take on UI building that WPF is supposed to represent. What do you think?
But most importantly: can anyone show me a code-free workaround for this seemingly trivial problem? Preferably without terrible hacks like this one.
I wrote a markup extension that allows an InputBinding's Command to be databound :
<KeyBinding Modifiers="Control" Key="E" Command="{input:CommandBinding EditCommand}"/>
Your situation is slightly different since you want to bind the CommandParameter, but you can probably adapt my code to fit your case. Note that this code uses private reflection, which only works in full-trust, and can be broken in later versions of WPF (actually it is broken in WPF 4.0... I can post a modified version if you need it).
Another option is to use the CommandReference class that can be found in the MVVM toolkit :
<Window.Resources>
<c:CommandReference x:Key="EditCommandReference" Command="{Binding EditCommand}"/>
</Window.Resources>
...
<KeyBinding Modifiers="Control" Key="E" Command="{StaticResource EditCommandReference}"/>
Again, this is for binding the Command property, but can probably be adapted to bind the CommandParameter...
The new way to solve this problem is by using Expression Triggers / Actions which allow you to set up keyboard shortcuts on arbitrary controls that do custom actions (like firing a Command).

Resources