Как использовать AlternationIndex в ItemsControls?

я видел некоторые статьи, которые показывают, как использовать AlternationIndex С ListBoxes или ListViews, но я потратил несколько часов, пытаясь получить чередующиеся цвета фона на базе ItemsControl класс и ничего не работает. Все!--3--> образцы, которые я видел использовать ListBoxItem в качестве целевого типа для стиля, который задает фон на основеAlternationIndex - как этот из MSDN:

<Grid>
    <Grid.Resources>
        <Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
            <Setter Property="Background" Value="Blue"/>
            <Setter Property="Foreground" Value="White"/>
            <Style.Triggers>
                <Trigger Property="ListBox.AlternationIndex" Value="1">
                    <Setter Property="Background" Value="CornflowerBlue"/>
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
                <Trigger Property="ListBox.AlternationIndex" Value="2">
                    <Setter Property="Background" Value="LightBlue"/>
                    <Setter Property="Foreground" Value="Navy"/>
                </Trigger>
            </Style.Triggers>
        </Style>

    </Grid.Resources>
    <ListBox AlternationCount="3" ItemsSource="{StaticResource data}" 
             ItemContainerStyle="{StaticResource alternatingWithTriggers}">
    </ListBox>
</Grid>

я хочу использовать ItemsControl потому что я не хочу функциональность выбора и я думаю рестайлинг в ListBox скрыть это может быть не лучший выбор.

это одна из вещей, которые я пробовал:

<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
    <Grid>
        <!-- some content here -->
    </Grid>
</DataTemplate>

<!-- ... -->

<ItemsControl
    ItemsSource="{Binding ObservableCollectionItems}"
    AlternationCount="2"
>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Style.Triggers>
                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                    <Setter Property="Grid.Background" Value="Red"></Setter>
                </Trigger>
                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                    <Setter Property="Grid.Background" Value="Blue"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

проблема, которую я видел, заключалась в том, что визуальное дерево имеет список ContentPresenterчто есть ItemsControl.AlternationIndex переключение между 0 и 1, но Grid в каждом элементе ContentPresenter и ItemsControl.AlternationIndex значение 0.

вероятно, есть что-то очевидное, чего мне не хватает...

5 ответов


ItemContainerStyle применяется к элементам, генерируемым ItemsControl: ContentPresenter. ContentPresenter, в свою очередь, будет содержать все, что вы поместите в свой ItemTemplate. В случае ListBox, ItemContainerStyle применяется к созданному ListBoxItem.

AlternationCount, основываясь на том, что вы разместили, доступен только для этих сгенерированных элементов. Вы не можете использовать ItemContainerStyle для установки фона сетки, потому что сетка неизвестна этому Стиль.

следующее Было бы идеальным, но, к сожалению, ContentPresenter не имеет свойства фона. Однако он будет работать для ListBox (с ListBoxItems).

<ItemsControl
    ItemsSource="{Binding ObservableCollectionItems}"
    AlternationCount="2">
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Style.Triggers>
                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                    <Setter Property="Background" Value="Red"></Setter>
                </Trigger>
                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                    <Setter Property="Background" Value="Blue"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

таким образом, вы в конечном итоге пишете стиль для сетки, которая привязывается к AlternationIndex вашего родительского ContentPresenter.

<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
    <Grid>
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0">
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1">
                        <Setter Property="Background" Value="Blue"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
    </Grid>
</DataTemplate>

хм .. Примерно через 2 часа я, наконец, нашел решение, которое просто работает:

       <ItemsControl ItemsSource="{Binding}" AlternationCount="2">
              <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid Background="Transparent" x:Name="__PART_GRID"></Grid>
                        <DataTemplate.Triggers>
                            <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                                <Setter TargetName="__PART_GRID" Property="Background" Value="Red"/>
                            </Trigger>
                            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                                <Setter TargetName="__PART_GRID" Property="Background" Value="Blue"/>
                            </Trigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
         </ItemsControl>

Я надеюсь, что этот ответ поможет другим сэкономить время.


или, как я нашел на другом посту, и он отлично работает для меня... Вы можете просто использовать привязку...

{Binding
    RelativeSource={RelativeSource Mode=TemplatedParent}, 
    Path=(ItemsControl.AlternationIndex)}

NB: не забудьте добавить AlterationCount= " 100 " на свой ItemsControl


если вы не хотите использовать DataTemplate подход, вы можете создать пользовательский элемент управления, который использует ContentControl в качестве контейнера элемента, поэтому позволяет указать цвет фона.

класс:

public class ItemsControlAlternating : ItemsControl
{
    static ItemsControlAlternating()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating),
                 new FrameworkPropertyMetadata(typeof(ItemsControlAlternating)));
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ContentControl();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is ContentControl;
    }
}

Словарь Ресурсов:

<Style TargetType="{x:Type c:ItemsControlAlternating}">
   <Setter Property="AlternationCount" Value="2"/>
   <Setter Property="Template">
       <Setter.Value>
           <ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}">
               <ItemsPresenter/>
           </ControlTemplate>
       </Setter.Value>
   </Setter>
   <Setter Property="ItemContainerStyle">
       <Setter.Value>
           <Style TargetType="{x:Type ContentControl}">
               <Setter Property="Template">
                   <Setter.Value>
                       <ControlTemplate TargetType="{x:Type ContentControl}">
                           <Border Background="{TemplateBinding Background}">
                               <ContentPresenter/>
                           </Border>
                       </ControlTemplate>
                   </Setter.Value>
               </Setter>
               <Style.Triggers>
                   <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                       <Setter Property="Background" Value="Gray"/>
                   </Trigger>
                   <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                       <Setter Property="Background" Value="White"/>
                   </Trigger>
               </Style.Triggers>
           </Style>
       </Setter.Value>
   </Setter>
</Style>

Я не знаю, как любой из предыдущих ответов является законным. Я не мог заставить ни одного из них работать (хотя и не пробовал Джейкоби). В любом случае, я нашел путь к просветлению здесь:http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, что приводит меня к добавлению следующего в xaml.код cs-за:

public sealed class CustomItemsControl : ItemsControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ContentControl();
    }
}

и это в самом xaml

    <local:CustomItemsControl AlternationCount="2" 
          ItemsSource="{Binding Cells, Mode=OneWay}">
        <local:CustomItemsControl.ItemContainerStyle>
            <Style TargetType="ContentControl">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ContentControl">
                            <Border Background="{TemplateBinding Background}">
                                <ContentPresenter/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

                <Style.Triggers>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                        <Setter Property="Background" Value="WhiteSmoke"/>
                    </Trigger>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </local:CustomItemsControl.ItemContainerStyle>
    </local:CustomItemsControl>

Это было так чертовски трудно найти рабочее решение, что я действительно зол