Search code examples
c#wpfxamlbindingrelativesource

Bind to AlternationIndex of ItemsControl in ItemsControl


Consider the following XAML

<ItemsControl ItemsSource="{Binding Path=MyItems, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" AlternationCount="999" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex), 
                                        RelativeSource={RelativeSource TemplatedParent}, 
                                        FallbackValue=FAIL, 
                                        StringFormat={}Index is {0}}" />
                <ItemsControl ItemsSource="{Binding Path=MySubItems, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=1}, Path=(ItemsControl.AlternationIndex)}"/>
                                <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}, Path=(ItemsControl.AlternationIndex)}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

There are three TextBlock nodes. The 1st TextBlock is a direct child of the 1st ItemsControl, and shows the AlternationIndex, as expected. However, I need that AlternationIndex a level deeper, in the second ItemsControl. Therefore I can't use TemplatedParent and thought I could find the Ancestor with AncestorLevel. However, both TextBlock nodes in the 2nd ItemsControl show "0".

What I'm I missing? How do I target the 1st ItemsControl from within the 2nd ItemsControl?


Solution

  • The AlternationIndex won't be on the ItemsControl but on each of its children. Using DataTemplate your ItemsControl will store each children in a ContentPresenter which will have the AlternationIndex. What you need to modify:

    <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}, AncestorLevel=2}, Path=(ItemsControl.AlternationIndex)}"/>
    <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}, AncestorLevel=2}, Path=(ItemsControl.AlternationIndex)}"/>