ListBoxItem的Interaction.Triggers

时间:2018-06-20 09:36:15

标签: wpf xaml

如何为整个Interaction.Triggers设置ListBoxItem?我见过this question,但答案并未使用互动子。甚至有可能吗?

目前我有ListBox这样的人:

<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>

看起来像这样: list box preview

即使我单击红色Border以外的位置,我也想触发特定项目的事件触发器。

1 个答案:

答案 0 :(得分:1)

最简单的方法是在视图的代码背后处理ListBoxItem的事件并从那里调用命令:

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>

不,这不会破坏MVVM模式,因为您仍在从完全相同的视图调用完全相同的命令。

另一种选择是使用封装上述功能的attached behaviour并设置附加属性,如下所示:

<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>

如果您打算在多个不同的视图中重用此功能,则这样做可能很有用。否则,您可以使用代码隐藏选项。 MVVM并不是要从视图中消除代码。这是关于关注点分离的,仅仅是因为您实际上可以在XAML中做某事,但这并不意味着您总是应该这样做。