Search code examples
wpfxamllistviewbindingdatatemplate

How do I set a binding to an outer listview item from within an inner listview?


If one wants to display an actual listview item (not a property of it) one uses

<ListView Name="FirstExample" ItemsSource="{Binding CityList}" Width="Auto" Height="Auto">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding }"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

with

public List<String> CityList { get; set; } = new List<string> { "Paris", "New York" };
public List<String> Repeats { get; set; } =  new List<string> { "One", "Two" };

in the view model, using that lonely Text="{Binding }" there works as expected, to give us

Paris

NewYork

But How do you access the actual items of the outer listview if what's inside the datatemplate is setting a new datacontext? I want the code below to result in

Paris

Paris

New York

New York

but how do I set that Path={Binding ????? I've tried every variation I can think of, and very much searching as well. The use of relativesource and ancestorlevel=2 seems to get at the right listview, but I just can't get the path right.

The purpose of this is obviously not this silly example. In the actual code I need to get the outerlist view item into a multiconverter which takes data from both the inner and outerlist view.

<ListView Name="OuterListView" ItemsSource="{Binding CityList}" Width="Auto" Height="Auto">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ListView Name="InnerListView" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.Repeats}" Width="Auto" Height="Auto">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock  Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}, AncestorLevel=2}, Path={Binding ????? }}"/>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

Solution

  • You have to take ListViewItem as RelativeSource with AncestorLevel=2 and access it's DataContext:

    <ListView Name="OuterListView" ItemsSource="{Binding CityList}" Width="Auto" Height="Auto">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Background="SeaGreen">
                    <TextBlock  Text="{Binding }"/> <!-- entry from outer list -->
                    <ListView Name="InnerListView" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.Repeats}" Width="Auto" Height="Auto">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Background="Magenta">
                                    <TextBlock  Text="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListViewItem, AncestorLevel=2}}"/><!-- entry from outer list -->
                                    <TextBlock  Text="{Binding }"/> <!-- entry from inner list -->
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>