Search code examples
c#wpfitemscontrolstackpanel

How to change itemsControl stackpanel background color


Says I have a list of 10 items someList, I will show them on my page via itemsControl like below:

<ItemsControl DataContext="{Binding [someViewModel]}" 
              BorderBrush="Black" 
              ItemSource="{Binding someList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderThickness="1" Background="Green">
                <StackPanel MouseDown="{Binding Path=DataContext.someCommand,   
                                        RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}}" 
                                        Command Parameter="{Binding someID}">
                    <TextBlock Text="{Binding something}">
                </StackPanel>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

I do able to trigger someCommand method and I do able to pass in someID as input parameter. Now I'm wondering how to update the stackPanel background color, making it looks like "selected". Meaning now all item will have a green background, when I click on one of the stackpanel, that stackpanel should change background to red and change others back to green


Solution

  • If you want to use ItemsControl you can change ItemTemplate to RadioButton with custom ControlTemplate that will include Border which Background would change to Red when IsChecked == true:

    <ItemsControl DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <RadioButton Content="{Binding something}" GroupName="radioGroup">
                    <RadioButton.Template>
                        <ControlTemplate TargetType="{x:Type RadioButton}">
                            <Border Background="Green" x:Name="PART_Border">
                                <ContentPresenter/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="PART_Border" Property="Background" Value="Red"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </RadioButton.Template>
                </RadioButton>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    However I don't see a reason why you cannot use ListBox with SelectionMode=Single (default value) and change Template of ListBoxItem:

    <ListBox DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Border Background="Green" x:Name="PART_Border">
                                <ContentPresenter/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter TargetName="PART_Border" Property="Background" Value="Red"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
    

    or even do something like this, without changing Template:

    <ListBox DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
        <ListBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
        </ListBox.Resources>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Background" Value="Green"/>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
    

    In WPF it's generally much easier to pick a control that has functionality that you need and style it to look like you want then do this the other way round