0

I'm trying to change my ContentTemplate using this code:

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

But, when I click on the item, it keeps selecting random item or selecting the first item only. The point is I want to use different Image and add an overlay to the selected item.

Random click

Fahmi Noor Fiqri
  • 441
  • 7
  • 15

2 Answers2

1

I'm not sure what's going on in your case, but it's a bit suspicious that your ContentTemplate never defines a ContentPresenter. Anyway, I think there's another way to achieve your goal. Try the following 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>

You define an ItemTemplate, and depending on whether the ListBoxItem it's in is selected, you choose whether to use the overlay and the SelectedImage property. The ListBoxItem.ControlTemplate is replaced with an empty ContentPresenter to remove all default highlighting (since you're doing that yourself).

redcurry
  • 2,381
  • 2
  • 24
  • 38
0

It turns out this strange behavior is caused by DragMoveBehavior from this post.

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();
        }
    }
}

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

By removing the behavior from Window, this strange random click problem disappeared. Thanks to redcurry for the answer, I also used your code in my app.

UPDATE

I'm marking redcurry as the accepted answer for the code, but if you encounter this problem you might want to try his solution first before trying mine.

Fahmi Noor Fiqri
  • 441
  • 7
  • 15