Search code examples
c#wpfbindingitemscontrol

How can the property of object in an inner ItemsControl bind to the property of an object in an outer ItemsControl?


The title might sound convoluted but bear with me.

I have Rooms which contain Occupants:

public class Room
{
    public string Name { get; set; }
    public List<Person> Occupants { get; set; }
    public bool AreOccupantsEditable { get; set; }
}

public class Person
{
    public string Name { get; set; }
}

Here's an array of Rooms:

<ResourceDictionary>
    <x:Array x:Key="Rooms" Type="local:Room">
        <local:Room Name="Happy Room" AreOccupantsEditable="True">
            <local:Room.Occupants>
                <local:Person Name="Mindy" />
            </local:Room.Occupants>
        </local:Room>
        <local:Room Name="Sad Room" AreOccupantsEditable="True">
            <local:Room.Occupants>
                <local:Person Name="Bob" />
                <local:Person Name="Jane" />
            </local:Room.Occupants>
        </local:Room>
        <local:Room Name="Kill Room" AreOccupantsEditable="False">
            <local:Room.Occupants>
                <local:Person Name="Mork" />
                <local:Person Name="Dave" />
                <local:Person Name="Ryan" />
            </local:Room.Occupants>
        </local:Room>
    </x:Array>
</ResourceDictionary>

Here is an ItemsControl in an ItemsControl, to display rooms and their occupants:

<ItemsControl ItemsSource="{Binding Source={StaticResource Rooms}}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <!-- room name -->
                <TextBlock Text="{Binding Path=Name}" />
                <ItemsControl ItemsSource="{Binding Path=Occupants}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <!-- occupant name -->
                            <TextBox Text="{Binding Path=Name}" Margin="20,0,0,0" IsEnabled="{Binding ???}" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Without Person having a reference to Room, how can I bind the IsEnabled property of the TextBox to the AreOccupantsEditable property of the Room a Person is in?

If it helps, here's an example project: http://dl.dropbox.com/u/4220513/ItemsControl-Binding.zip


Solution

  • You can use RelativeSource to access the outer DataContext :

    IsEnabled="{Binding Path=DataContext.AreOccupantsEditable, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"