MVVM WPF bindings with RelativeSource - c#

<DataTemplate DataType="{x:Type local:TestModel}">
<Button Content="Button" " Margin="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<mvvm:EventToCommand
Command="{Binding ImageClick, Mode=OneWay}"
MustToggleIsEnabledValue="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
Hi all,
Above I have a data template which is switching on certain data type using a data template. I am using the mvvm pattern. I want to be to bind to the ImageClick property.
I was able to do this before, but since I have moved the button inside the data template I am unable to bind to that property.
I think I need to use Relative source for the binding but am really unsure how to do it.
Help on this would be amazing.
Thanks.

You may try the below.
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type YourViewModel}}, Path=DataContext.ImageClick}" />
I think it would help you..

Related

Context menu event or trigger of a control inside an itemtemplate of a listview is not fired

I've got following problem. Following situation in my xaml code:
<ListView ItemsSource="{Binding ListViewItems}">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
</ContextMenu>
</Label.ContextMenu>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding LabelMouseUpCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
After clicking a label no context menu is shown and the trigger does not work as well, LabelMouseUpCommand method is not entered. I fear the listview handles the click itself and does not pass it to the embedded controls.
Is there any way to pass it to the controls. In future i want to add several controls to the itemtemplate and everyone has it own different context menu.
I found the answer for my problem with this stackoverflow article
There the author explains that the contextmenu does not lie in the same visual tree as the listview. Therefore my initial binding can't work because the source can't be found within the visual tree.
Furthermore Sinatr was totally right, the trigger was initially defined for listview, not for the label.
Here is my working code:
<ListView ItemsSource="{Binding ListViewItems}" x:Name="listViewMain">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding DataContext.MenuItems, Source={x:Reference listViewMain}}">
</ContextMenu>
</Label.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding DataContext.LabelMouseUpCommand, Source={x:Reference listViewMain}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Clear / Erase TextBox Content With Button Click Event

I have the following XAML snippet:
<TextBox x:Name="FilterTB" TextChanged="FilterTB_TextChanged"/>
<Button x:Name="CancelFilterSelectionButton" FontWeight="Bold" Content="X"/>
I'd like to erase the content of the TextBox when the user presses the Button.
Of course doing so from Code Behind is a trivial task, but I wanted to accomplish it only through the use of XAML, and so using Triggers.
I tried researching on the net, but I either found uncorrect solutions, or overly-convoluted solutions, so I'd like to hear some clean and compact solutions.
Here I had a spare minute, hope this helps, cheers.
namespaces;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
and easy peasy.
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBox x:Name="ThatThangToClear" Width="250"/>
<Button x:Name="ClearThatThang" Content="Clear That Thang" Margin="5,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction
TargetName="ThatThangToClear"
TargetObject="{Binding ElementName=ThatThangToClear}"
PropertyName="Text" Value="{x:Null}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
Oh, and P.S. - You really only need either TargetName OR TargetObject but I included both for examples sake.

Can't detect Right Click on listBox in MVVM

I don't understand why I can't detect right click on my list box when I use an MVVM.
I use the event trigger but some events doesn't work.
<ListBox x:Name="PlaylistsList" ItemsSource="{Binding PlaylistsList}" HorizontalAlignment="Left">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseRightButtonDown">
<i:InvokeCommandAction Command="{Binding NewPlaylistCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
My command "NewPlaylistCommand" is never call. Could you help me ?
Thank you.
EDIT:
I found solution to my problem, I used the ContextMenu to interact with my ListBoxItem
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="ListBox">
<TextBlock Text="{Binding Name}"/>
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Rename" Command="{Binding RenamePlaylistCommand}"/>
<MenuItem Header="Delete" Command="{Binding DeletePlaylistCommand}" CommandParameter="{Binding SelectedValue, ElementName=PlaylistsList}"/>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Now I can right click on my item to Rename or Delete it.
Thank you for your help.
Most likely that something inside has swallowed your right click event and hence it has not bubbled up (I suspect it has something to do with context menu behaviors). You COULD use the Preview- events which bubble the other way.
The other solution you could use is to directly apply the interaction to each and every child in the list box (and their children as well).
However I honestly don't expect from a UI point of view that right clicking on a play list will create a new play list...I expect from my years of windows usage that a context menu should pop up, possibly with an "add new play list" menuitem.

How to fire a command on double-click listbox item using MVVM?

I'm trying to launch an ICommand when the user double-clicks on a listbox item. Also, I'm trying to do this using the MVVM pattern.
In this XAML, the key press "p" works perfectly. When I double click on the list box, the command never starts. I've set a break point to confirm "PlayVideoCommand" is not called with a double-click. Am I missing something or do I have to use Setter (which I'm not familiar with)?
<ListBox Name="SmallVideoPreviews" Grid.Column="1" MaxHeight="965"
ItemsSource="{Binding BrowseVideos}"
ItemTemplate="{StaticResource BrowseTemplate}">
<ListBox.InputBindings>
<KeyBinding Key="p"
Command="{Binding PlayVideoCommand}"
CommandParameter="{Binding ElementName=SmallVideoPreviews, Path=SelectedItem}"/>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding PlayVideoCommand}"
CommandParameter="{Binding ElementName=SmallVideoPreviews, Path=SelectedItem}"/>
</ListBox.InputBindings>
</ListBox>
Both double-click and "p" should execute the same command. When using the mouse, I can see the listboxitem is selected. I have a hunch that the MouseBinding Command property is not a dependency property but I don't know how to confirm this.
What's happening in your sample is that the listbox itself is reacting to the double click, but only in the part of it's area that is not covered by a list box item.
You need the event handler to be tied to the listboxitem.
Some ways to do it are here:
Double Click a ListBox item to open a browser
And some discussion about why a little code-behind in MVVM is not necessarily a terrible thing:
Firing a double click event from a WPF ListView item using MVVM
More discussion:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/9fb566a2-0bd6-48a7-8db3-312cd3e93340/
It seems that the ListBox doesn't handle double click on a ListBoxItem. This is a good answer:
Can't bind Command to ListBox
One could argue weather or not code-behind is terrible, but it ís possible use a command. Add the LeftDoubleClick gesture to the ItemTemplate like this:
<UserControl.Resources>
<DataTemplate x:Key="BrowseTemplate" >
<StackPanel >
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding DataContext.PlayVideoCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Mode=OneWay}"
CommandParameter="{Binding }" />
</StackPanel.InputBindings>
<TextBlock Text="{Binding }" Width="50" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>

Apply multiple AttachedCommandBehaviors using a style

I am trying to use AttachedCommandBehavior V2 to translate ListBoxItem events such as double click into commands that are execute against the view model.
I want to fire commands for multiple events, this is the example code I am trying to emulate:
<Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test">
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseLeftButtonDown" Action="{Binding DoSomething}" CommandParameter="An Action on MouseLeftButtonDown"/>
<local:BehaviorBinding Event="MouseRightButtonDown" Command="{Binding SomeCommand}" CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
<TextBlock Text="MouseDown on this border to execute the command"/>
</Border>
Since I want to apply that to a ListBoxItem, I am trying to do it through a style by doing:
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="acb:CommandBehaviorCollection.Behaviors">
<Setter.Value>
<acb:CommandBehaviorCollection>
<acb:BehaviorBinding Event="MouseDoubleClick" Command="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}"/>
<acb:BehaviorBinding Event="KeyUp" Command="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}"/>
</acb:CommandBehaviorCollection>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
But I get a compile error with that code that says error MC3089: The object 'CommandBehaviorCollection' already has a child and cannot add 'BehaviorBinding'. 'CommandBehaviorCollection' can accept only one child. Line 39 Position 11.
Also if I comment out one of the BehaviorBindings then it compiles but I get a runtime xaml load exception saying "Value cannot be null. Parameter name: property", so I'm not sure if I'm even taking the correct approach.
Can anyone provide an example of the correct syntax to set multiple behavior bindings on a ListBoxItem?
My solution uses interaction triggers and the ItemTemplate not the ItemContainerStyle.
This invokes a mouse double click or key up command in the text box, not the whole list box item.
<UserControl.Resources>
<DataTemplate DataType="{x:Type ViewModel:DataItem}" x:Key="ItemTemplate">
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DoubleClickCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding KeyUpCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox Text="{Binding Name}">
</TextBox>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
<ListBox x:Name="listBox" ItemTemplate="{StaticResource ItemTemplate}" ItemsSource={Binding Items} />
Where DataItem is something like
class DataItem : INotifyPropertyChanged
{
public string Name{get;set}
.. etc
}
and the view model set on the DataContext has an IList<DataItems> Items{get; private set} property.

Categories

Resources