简体   繁体   中英

Variable background color in an itemscontrol

I would like to create an items control that alternates the background color of an item based on the alternation index of the group it belongs to. In reference to the classes I list below, I would like it to, for example, have the background of the first three RandomHouse books as black, and then when it encounters the next Publisher, the background changes back to white, and so on and so forth for as many unique publishers there are. The number and name of the publishers is nondeterministic and is only evaluated at runtime. I have tried to do it with xaml to the best of my ability but it doesnt seem the alternationindex can be accessed for a GroupItem for whatever reason. Any help would be appreciated.

class Book
    {
        String Publisher {get; set;}
        String Title     {get; set;}
    }

    class ViewModel
    {
        var listBooks = new ObservableCollection<Book>();
        listBooks.Add(new Book(){Publisher = "RandomHouse", Title = "Title1"});
        listBooks.Add(new Book(){Publisher = "RandomHouse", Title = "Title2"});
        listBooks.Add(new Book(){Publisher = "Penguin", Title = "Title5"});

        ObservableCollection<Book> ListBookItems {get {return listBooks.Orderby(e => e.Publisher).ToList(); } }
    }

<UserControl.Resources>
        <Style TargetType="ItemsControl" x:Key="ListBookStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <ScrollViewer CanContentScroll="True">
                            <ItemsPresenter/>
                        </ScrollViewer>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>

            <Setter Property="FontFamily">
                <Setter.Value>Consolas</Setter.Value>
            </Setter>
        </Style>

        <DataTemplate DataType="{x:Type models:Book}">
            <Grid IsSharedSizeScope="True">

                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="Publisher" Width="100"/>
                    <ColumnDefinition SharedSizeGroup="Title" Width="100"/>

                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <TextBlock 
                    HorizontalAlignment="Left"
                    Text="{Binding Publisher}" 
                    Grid.Column="0"
                    FontWeight="Bold" 
                    Margin="5"/>

                <TextBlock 
                    HorizontalAlignment="Left"
                    Text="{Binding Title}" 
                    Grid.Column="1"
                    FontWeight="Bold" 
                    Margin="5" 
                     />
            </Grid>
        </DataTemplate>
        <CollectionViewSource x:Key="ListBookItems" Source="{Binding ListBookItems}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Publisher"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </UserControl.Resources>

    <DockPanel>
        <ItemsControl 
            ItemsSource="{Binding Source={StaticResource ListBookItems}}" 
            Style="{StaticResource ListBookStyle}">
            <ItemsControl.GroupStyle>
                <GroupStyle AlternationCount="2">
                    <GroupStyle.ContainerStyle >
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Foreground" Value="#FF444444"/>
                            <Setter Property="Background" Value="#FF000000"/>
                            <!--<Style.Triggers>
                                <Trigger Property="AlternationIndex"  Value="0">
                                    <Setter Property="Foreground" Value="#FF444444"/>
                                    <Setter Property="Background" Value="#FFD9D9D9"/>
                                </Trigger>
                                <Trigger Property="AlternationIndex" Value="1">
                                    <Setter Property="Foreground" Value="#FF444444"/>
                                    <Setter Property="Background" Value="#FFEFEFEF"/>
                                </Trigger>
                            </Style.Triggers>-->
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ItemsControl.GroupStyle>
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer CanContentScroll="True">
                        <ItemsPresenter/>
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel IsItemsHost="True"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

        </ItemsControl>
    </DockPanel>

You are very close. You just need to specify ItemsControl.AlternationIndex as the property name in each trigger, instead of just AlternationIndex .

That said, frankly I had second-thoughts about even proposing this as an answer, except that I can't actually get that to work. That is, while I can see in the debugger that it correctly sets the GroupItem.Background property value as desired, I see no visible effect on-screen. It's as if the items-presenter for the group is ignoring the GroupItem 's background property.

The reason I'm going ahead and posting this as an answer even though it doesn't completely address the issue is that getting the GroupItem.Background property value to be respected by the actual presenter in the GroupItem is a completely different problem than correctly using the AlternationIndex value. So while you can use this answer to get the AlternationIndex value to be correctly bound, you will need to do some more work and/or post another question to dig into why having correctly set the Background property value, that does not actually change the background as shown on the screen.


I wish I could also explain how to get the background property in GroupItem to affect the display on the screen. I hope that if you figure that out, you will at least follow up with a comment here, explaining the answer. :) (Or if you post a question and someone else explains it, comment with a reference to that answer).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM