Styling a ListBoxItem depending on its index in the ListBox

listbox, listboxitem, multidatatrigger, wpf, xaml

Solution

See `AlternationIndex`. (You can use a very high `AlternationCount` to ensure that only the first item has index `0` and trigger on that).

This is a bit abusive, a cleaner method would be a value converter / multi value converter, that gets the index via something like `listBox.Items.IndexOf(currentItem)`.

Problem

I want to change the margin of the first item in the ListBox if SomeProperty value is 10, without code-behind. This is what I have so far: ``` <ListBox x:Class="Windows.CustomList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Windows" mc:Ignorable="d" x:Name="MyList" d:DesignHeight="300" d:DesignWidth="300"> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=SomeProperty}" Value="10"/> <Condition Binding="{Binding Path=Items.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" Value="1" /> </MultiDataTrigger.Conditions> <Setter Property="Margin"> <Setter.Value> <Thickness Left="500"/> </Setter.Value> </Setter> </MultiDataTrigger> </Style.Triggers> </Style> </ListBox.ItemContainerStyle> <ListBox.ItemTemplate> <DataTemplate> <local:ListBoxItemCustomTemplate/> </DataTemplate> </ListBox.ItemTemplate> <ListBox.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> </ListBox> ``` When I try this approach I get: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='ListBox', AncestorLevel='1''. BindingExpression:Path=Items.Count; DataItem=null; target element is 'ListBox' (Name=''); target property is 'NoTarget' (type 'Object') If I have only the first condition, it applies the margin properly. Another way I tried was by using the ElementName: This approach doesn't give any error but it's not working either. Any help would be much appreciated.

Original source