【问题标题】:Interaction.Triggers for ListBoxItemListBoxItem 的 Interaction.Triggers
【发布时间】:2018-06-20 18:13:25
【问题描述】:

如何为整个ListBoxItem 设置Interaction.Triggers?我见过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>

看起来像这样:

即使我在红色Border 之外单击,我也想触发特定项目的事件触发器,目前还没有发生。

【问题讨论】:

    标签: wpf xaml


    【解决方案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 中做某事,并不意味着您总是应该这样做。

    【讨论】:

    • 解决方案背后的代码对我有用,它看起来也很优雅,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    相关资源
    最近更新 更多