Grid "Tap" or "Click" event through a data template? - c#

I have already tried searching the web for using commands in Windows Phone, but I can't find a scenario that fits my problem. I have a DataTemplate which creates some grids. For these grids, I want them to do something when their Click event is triggered. However, the Grid element doesn't have a Command property.
I don't nescessarily need to do it through commands, but I thought that was the way to go.
Here's what I want to do.
<ItemsControl VerticalAlignment="Top" Visibility="Collapsed" x:Name="RadioList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="12" Tag="{Binding}">
<!-- this is the grid I want to listen for clicks on -->
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

To bind a command to a grid you will need to use EventTrigger:
<ItemsControl VerticalAlignment="Top" Visibility="Collapsed" x:Name="RadioList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="12" Tag="{Binding}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding YourCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
with the following namespace definition:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Related

Cant get InputBinding to apply to entire ListBoxItem using DataTemplate WPF

Trying to get some keybindings onto my ListBoxItems in a ListBox in WPF. I am using MVVM, and binding the ItemSource of the ListBox to a list of ViewModels. This ViewModel has a string and a boolean for 'Selected'. I wish to display Selected as a property to a CheckBox.
I am trying to make it so that if I navigate the list items with the up and down arrows on the keyboard, and then press enter/space/whatever, I can toggle the Checkbox. However, I have to press tab first, to get focus to the StackPanel which contains the checkbox.
<DataTemplate x:Key="MyTemplate" DataType="{x:Type ViewModel}">
<Border Width="2" BorderBrush="Blue">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding EnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<CheckBox VerticalAlignment="Center"
Content="{Binding Name}"
IsChecked="{Binding Selected}"
Margin="3" />
</Border>
</DataTemplate>
=======================
<Popup x:Name="FilterPopup" Grid.Column="1"
IsOpen="{Binding IsChecked, ElementName=FilterButton}"
StaysOpen="False"
PlacementTarget="{Binding ElementName=FilterButton}"
Placement="Top">
<ListBox ItemsSource="{Binding ViewModels}"
ItemTemplate="{StaticResource MyTemplate}" />
</Popup>
Have I missed something obvious???
The triggers above are fired inside the data template, not inside item container. So if the last one is focused there is no effect.
To avoid this, the triggers should be specified on item container level:
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="l:Attach.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Command="{Binding EnterCommand}" Key="Enter" />
<KeyBinding Command="{Binding EnterCommand}" Key="Space" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
I've taken a way to set input bindings from style from this question.

Adding a list of key bindings

In my WPF MVVM application each model-view contains a list of buttons. Which are valid for that user control.
private List<myButton> _buttons;
I am displaying them like this:
<ItemsControl ItemsSource="{Binding buttons}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="100" Height="40" VerticalAlignment="Top" Margin="5,5,5,5" Command="{Binding command}" Content="{Binding name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Which works just fine.
Now what i would like to do is have key bindings on some of my buttons Save for example cntr + s.
How do I add key bindings for some of the buttons. From what i have found so far you would do something like this
<Window.InputBindings>
<KeyBinding Key="Z" Modifiers="Ctrl" Command="{StaticResource MyCommand1}" />
<KeyBinding Key="H" Modifiers="Alt" Command="{StaticResource MyCommand2}" />
</Window.InputBindings>
I tried adding it as a list but that didnt work at all. There must be a way of bulding the key bindings for the some of my buttons.
I got it!
The thing is that Inputbindings are a window thing not a user control thing. Yes I am new at WPF.
By adding the following to the Mainwindow.xml it will fire savecommand on which ever usercontrol is currently selected.
<Window.InputBindings>
<KeyBinding Key="s" Modifiers="Ctrl" Command="{Binding ElementName=ListBoxMenu, Path=SelectedItem.SaveCommand }" />
</Window.InputBindings>
If the usercontrol / modelview what ever its called doesn't have a savecommand it just does nothing.

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>

Canvas that allows events for overlapped elements

I am looking for a way in WPF to recognize click events on all ZIndex levels. So this means I would like to recoginze a click also if another element (on the same canvas - only different ZIndex) is clicked.
What I want to achive with this functionality is that I have some ListBoxes on the same canvas and I would like to get the SelectionChanged event also when they overlap.
Edit: Added some code.
<DataTemplate DataType="{x:Type my:type}">
<ListBox SelectionMode="Extended" Background="Transparent"
ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Elements}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<ei:CallMethodAction TargetObject="{Binding ElementName=control, Path=DataContext}"
MethodName="SelectionChanged" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="500" IsItemsHost="True"
Height="500"
VerticalAlignment="Top" HorizontalAlignment="Left" Background="Transparent">
</Canvas >
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
<DataTemplate>
In this example the SelectionChanged handler is only visible for one object (depending on ZIndex).

add command on ItemTemplate selection

This is a pretty easy question I think , but I can't find the answer. I have an itemtemplate defined into a datatemplate. When an item is selected, I wanna trigger a command to select the name of my element and apply it somewhere else. For the moment the MouseDown event doesn't accept my command.
<ListView Margin="4" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Path=ExistingStateInfos, ElementName=Window}"
SelectedItem="{Binding Path=SelectedStateInfo, ElementName=Window}" x:Name="statinfoListview">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static MyWindow.ApplyStateInfoNameToStateCommand}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You can't set a command directly to an event handler.
Use EventToCommand from the MVVM LightToolkit
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<Command:EventToCommand Command="{Binding YourCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
In fact ot was bulshit from me, I just add to do
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static ApplyStateInfoNameToState_Click}" />
Sorry it's friday. Have a nice weekend :)

Categories

Resources