Как использовать AlternationIndex в ItemsControls? - PullRequest
26 голосов
/ 25 августа 2010

Я видел несколько статей, которые показывают, как использовать AlternationIndex с ListBox es или ListView s, но я потратил несколько часов, пытаясь получить чередующиеся цвета фона в базовом классе ItemsControl, и ничего не кажется работать. Все ListBox сэмплов, которые я видел, используют 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 ]

45 голосов
/ 25 августа 2010

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.

25 голосов
/ 14 ноября 2011

хм .. После 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>

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

2 голосов
/ 10 января 2018

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

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

Примечание: не забудьте добавить AlterationCount = "100" вваш ItemsControl

0 голосов
/ 11 ноября 2017

Я не знаю, насколько любой из предыдущих ответов является законным.Я не мог заставить кого-либо из них работать (хотя я и не пробовал у Якоби).В любом случае, я нашел путь к просветлению здесь: 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>

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

0 голосов
/ 11 декабря 2014

Если вы не хотите использовать подход 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>
...