Reputation: 135
How can I set Interaction.Triggers
for whole ListBoxItem
? I have seen this question, but the answer does not use interactons. Is it even possible?
Currently I Have ListBox
like this:
<ListBox ItemsSource="{Binding CharactersList}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="Focusable" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock x:Name="CharacterTextBlock" Text="{Binding}" Width="20" Height="20" TextAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CharacterClick}"
CommandParameter="{Binding}" />
</i:EventTrigger>
<i:EventTrigger EventName="TouchUp">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CharacterClick}"
CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to fire event trigger for specific item even if i click outside of red Border
, which is not happening at the moment.
Upvotes: 0
Views: 1579
Reputation: 169390
The easiest way to do this would be to handle the events for the ListBoxItem
in the code-behind of the view and invoke the commands from there:
private void ListBoxItem_MouseUp(object sender, MouseButtonEventArgs e) => InvokeCommand(sender);
private void ListBoxItem_TouchUp(object sender, TouchEventArgs e) => InvokeCommand(sender);
private void InvokeCommand(object sender)
{
ListBoxItem lbi = sender as ListBoxItem;
var vm = DataContext as YourViewModel;
if (vm != null)
vm.CharacterClick.Execute(lbi.DataContext);
}
XAML:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="Focusable" Value="False" />
<EventSetter Event="MouseUp" Handler="ListBoxItem_MouseUp" />
<EventSetter Event="TouchUp" Handler="ListBoxItem_TouchUp" />
</Style>
</ListBox.ItemContainerStyle>
And no, this does not break the MVVM pattern since you are still invoking the exact same commands from the exact same view.
The other option would be to use an attached behaviour that encapsulates the above functionality and set the attached properties something like this:
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="Focusable" Value="False" />
<Setter Property="local:YourBehavior.MouseUpCommmand" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CharacterClick}" />
<Setter Property="local:YourBehavior.MouseUpCommmandParameter" Value="{Binding}" />
<!-- ... -->
</Style>
It may be useful to do this if you intend to reuse this functionality across several different views. Otherwise you may go with the code-behind option. MVVM is not about eliminating code from the views. It's about separation of concerns and just because you actually can do something in XAML, it doesn't mean that you always should.
Upvotes: 3