user1572700
user1572700

Reputation: 133

How do I bind to a property of an object under a collection of collections?

I have an ObservableCollection of a class (TopLevel) that contains a name property and a list of another ObservableCollection of class (BottomLevel) that has just a name property. The binding on the highest list works, but when I try to bind to the property on the BottomList I get nothing. What am I missing here?

XAML:

<Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid x:Name="myGrid" DataContext="topList">
    <Border BorderBrush="AliceBlue" Grid.Column="0" BorderThickness="5">
        <ItemsControl x:Name="ic1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Path=TopName}"/>
                        <Border BorderBrush="AntiqueWhite" Grid.Column="1" BorderThickness="5">
                            <Button Content="{Binding Path=BottomList.BottomName}"/>
                        </Border>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>                
        </ItemsControl>            
    </Border>
</Grid>

Code behind:

public partial class MainWindow : Window
{
    public ObservableCollection<TopLevel> topList;
    public MainWindow()
    {
        InitializeComponent();
        topList = new ObservableCollection<TopLevel>();
        topList.Add(new TopLevel("T" + (1 + topList.Count).ToString()));
        topList[0].AddBottom();
        topList.Add(new TopLevel("T" + (1 + topList.Count).ToString()));
        topList[1].AddBottom();
        ic1.ItemsSource = topList;            
    }
}

public class TopLevel
{
    private ObservableCollection<BottomLevel> bottomList;
    private string topName;

    public void AddBottom()
    {
        bottomList.Add(new BottomLevel("B" + (1 + bottomList.Count).ToString()));
    }

    public TopLevel(string x)
    {
        bottomList = new ObservableCollection<BottomLevel>();
        topName = x;
    }

    public string TopName
    {
        get
        {
            return topName;
        }
        set
        {
            if (topName!=value)
            {
                topName = value;
            }
        }
    }

    public ObservableCollection<BottomLevel> BottomList
    {
        get
        {
            return bottomList;
        }
        set
        {
            if (bottomList!=value)
            {
                bottomList = value;
            }
        }
    }
}

public class BottomLevel
{
    private string bottomName;

    public BottomLevel(string x)
    {
        bottomName = x;
    }

    public string BottomName
    {
        get
        {
            return bottomName;
        }
        set
        {
            if (bottomName!=value)
            {
                bottomName = value;
            }
        }
    }
}

Upvotes: 1

Views: 153

Answers (2)

Dineshreddybandi
Dineshreddybandi

Reputation: 135

If you have only one item in BottomList Then you can use the below code for Button

 <Button Content="{Binding Path=BottomList[0].BottomName}" Height="50"/>

If you want to Bind the BottomList to some List Control you can bind to the DataGrid then you can use the below code.

<Grid x:Name="myGrid" DataContext="topList">
    <Border BorderBrush="AliceBlue" Grid.Column="0" BorderThickness="5">
        <ItemsControl x:Name="ic1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Path=TopName}"/>
                        <Border BorderBrush="AntiqueWhite" Grid.Column="1"    BorderThickness="5">
                            <DataGrid ItemsSource="{Binding Path=BottomList}" AutoGenerateColumns="False">
                                <DataGrid.Columns>
                                    <DataGridTemplateColumn>
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <Button Content="{Binding Path=BottomName}" Height="50"/>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                </DataGrid.Columns>
                            </DataGrid>
                          </Border>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Border>
</Grid>

Please let me know if you need any more help.

Upvotes: 1

BradleyDotNET
BradleyDotNET

Reputation: 61339

Your path for the button is incorrect. BottomList does not have a "Name" property, so you can't bind to it. Instead, just use BottomName as your path.

Since your topList has a collection of "BottomLevel" you'll need some sort of nested items control to iterate over the "bottomList" collection (then use "BottomName" for your path as above).

As it stands, you basically have:

<ItemsControl //List of TopLevel>
//Your data context is now the TopLevel item itself
<Button Path=/> //What goes here? you have a whole collection of BottomLevel items to choose from!
</ItemsControl>

Upvotes: 3

Related Questions