使用 Trigger 更改 DataTemplate 时随机选择的项目

Posted

技术标签:

【中文标题】使用 Trigger 更改 DataTemplate 时随机选择的项目【英文标题】:Random selected item when using Trigger to change DataTemplate 【发布时间】:2019-06-20 00:16:20 【问题描述】:

我正在尝试使用此代码更改我的ContentTemplate

<DataTemplate x:Key="SidebarItemStyle" DataType="x:Type domain:SidebarDataTemplate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle Grid.Row="0" Grid.RowSpan="2" Fill="StaticResource BluePrimaryBrush" />
        <Image Grid.Row="0" Style="StaticResource SidebarMenuImageSyle" Source="Binding Image" />
        <TextBlock Grid.Row="1" Style="StaticResource SidebarMenuTextStyle" Text="Binding Title" />
    </Grid>
    </DataTemplate>
<DataTemplate x:Key="SidebarSelectedItemStyle" DataType="x:Type domain:SidebarDataTemplate">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle Grid.Row="0" Grid.RowSpan="2" Fill="StaticResource BluePrimaryBrush" />
        <Rectangle Grid.Row="0" Grid.RowSpan="2" Fill="StaticResource TransparentOverlay1Brush" />
        <Image Grid.Row="0" Style="StaticResource SidebarMenuImageSyle" Source="Binding SelectedImage" />
        <TextBlock Grid.Row="1" Style="StaticResource SidebarMenuTextStyle" Text="Binding Title" />
    </Grid>
</DataTemplate>

<Style TargetType="x:Type ListBoxItem" x:Key="SidebarContainerStyle">
    <Setter Property="ContentTemplate" Value="StaticResource SidebarItemStyle" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="StaticResource SidebarSelectedItemStyle" />
        </Trigger>
    </Style.Triggers>
</Style>

但是,当我单击该项目时,它会一直选择随机项目或仅选择第一个项目。关键是我想使用不同的Image 并为所选项目添加叠加层。

【问题讨论】:

【参考方案1】:

我不确定你的情况是怎么回事,但你的ContentTemplate 从未定义ContentPresenter 有点可疑。无论如何,我认为还有另一种方法可以实现您的目标。尝试以下 XAML:

<ListBox ItemsSource="Binding Items">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Rectangle Grid.Row="0" Grid.RowSpan="2" Fill="StaticResource BluePrimaryBrush" />
                <Rectangle Grid.Row="0" Grid.RowSpan="2" Fill="StaticResource TransparentOverlay1Brush">
                    <Rectangle.Style>
                        <Style TargetType="Rectangle">
                            <!-- Don't show overlay when not selected -->
                            <Setter Property="Visibility" Value="Collapsed" />
                            <Style.Triggers>
                                <DataTrigger Binding="Binding IsSelected, RelativeSource=RelativeSource FindAncestor, AncestorType=ListBoxItem" Value="True">
                                    <!-- Show overlay when selected -->
                                    <Setter Property="Visibility" Value="Visible" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Rectangle.Style>
                </Rectangle>
                <Image Grid.Row="0">
                    <Image.Style>
                        <Style TargetType="Image">
                            <!-- Use Image when not selected -->
                            <Setter Property="Source" Value="Binding Image" />
                            <Style.Triggers>
                                <DataTrigger Binding="Binding IsSelected, RelativeSource=RelativeSource FindAncestor, AncestorType=ListBoxItem" Value="True">
                                    <!-- Use SelectedImage when selected -->
                                    <Setter Property="Source" Value="Binding SelectedImage" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Image.Style>
                </Image>
                <TextBlock Grid.Row="1" Text="Binding Title" />
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>

    <!-- Remove default selection highlighting -->
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <ContentPresenter />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

您定义了一个ItemTemplate,根据是否选择了它所在的ListBoxItem,您可以选择是否使用覆盖和SelectedImage 属性。 ListBoxItem.ControlTemplate 被替换为空的 ContentPresenter 以删除所有默认突出显示(因为您自己这样做)。

【讨论】:

感谢您的回复,我已经解决了这个问题,请查看我的更新答案。【参考方案2】:

原来这种奇怪的行为是由来自this post的DragMoveBehavior引起的。

public class DragMoveBehavior : Behavior<Window>

    protected override void OnAttached()
    
        AssociatedObject.MouseMove += AssociatedObject_MouseMove;
    

    protected override void OnDetaching()
    
        AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
    

    private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
    
        if (e.LeftButton == MouseButtonState.Pressed && sender is Window window)
        
            // In maximum window state case, window will return normal state and
            // continue moving follow cursor
            if (window.WindowState == WindowState.Maximized)
            
                window.WindowState = WindowState.Normal;

                // 3 or any where you want to set window location after
                // return from maximum state
                Application.Current.MainWindow.Top = 3;
            

            window.DragMove();
        
    

窗口 XAML:

<Window ...
        xmlns:h="clr-namespace:A.Namespace.Of.DragMoveBehavior"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Behaviors>
        <h:DragMoveBehavior />
    </i:Interaction.Behaviors>
    ...
</Window>

通过从 Window 中删除该行为,这个奇怪的随机点击问题消失了。感谢redcurry 的回答,我也在我的应用中使用了你的代码。

更新

我将redcurry 标记为代码的可接受答案,但如果您遇到此问题,您可能需要先尝试他的解决方案,然后再尝试我的解决方案。

【讨论】:

以上是关于使用 Trigger 更改 DataTemplate 时随机选择的项目的主要内容,如果未能解决你的问题,请参考以下文章

使用 Trigger 更改 DataTemplate 时随机选择的项目

RefluxJS 商店可以在调用 trigger() 时指示哪些属性已更改?

在 MySQL 的 TRIGGER 中更改 LAST_INSERT_ID()

php 在Shopkeeper主题中为XL WooCommerce Sales Trigger插件更改WooCommerce单一产品位置

Derby Trigger on UPDATE:如何更新时间戳?

在Trigger错误中设置TextDecoration