Home > OS >  How to bind to a collection inside of a collection?
How to bind to a collection inside of a collection?

Time:03-04

I'm trying to bind an itemscontrol to a collection inside of another collection. To do this, I've layered an itemscontrol inside of another itemscontrol, like so:

<ItemsControl ItemsSource="{Binding MachinistUnreportedOps}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding MultiJobOps}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <DataTemplate>
                    <TextBlock>
                        <Run Text="Op " />
                        <Run Text="{Binding JobOperation}" />
                    </TextBlock>
                </DataTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

This will eventually be bound to a source from entity framework, but since I was having issues I just put this dummy data in my viewmodel:

MachinistUnreportedOps = new ObservableCollection<SimpleClass>()
{
    new()
    {
        MultiJobOps = new()
        {
            new() { JobOperation = 100 },
            new() { JobOperation = 101 },
            new() { JobOperation = 102 },
        },
    },
    new()
    {
        MultiJobOps = new()
        {
            new() { JobOperation = 103 },
            new() { JobOperation = 104 },
            new() { JobOperation = 105 },
        },
    },
};

(SimpleClass pretty much just holds some data, which I am trying to access in the above xaml. Obviously it has a JobOperation property, which is an int.)

Unfortunately, the same issue arises with this data and using EF: System.Windows.Markup.XamlParseException: 'Add value to collection of type 'System.Windows.Controls.ItemCollection' threw an exception.'

with inner exception: System.InvalidOperationException: Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.

I've looked into this error, but most issues (like this one: Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead) seem to be about directly accessing the control and changing the items in it, which I'm not doing at all. I have no references to either itemscontrol in my code behind or viewmodel. I'm not even accessing the MachinistUnreportedOps collection in my code anywhere else, let alone modifying it. I figure I must be misunderstanding something about how ItemsControl works with its bound data. I'm still pretty new to WPF.

One thing I did find was an article I lost the link for, but it suggested defining an itemspanel as I did in the xaml above. No difference in behavior one way or the other. I don't much care what kind of panels are used, but grid would be nice for the inner itemscontrol as I hope to expand it.

CodePudding user response:

To put this in the form of an answer. Your XAML should be like what is below. The only change I made was to put your second DataTemplate inside an <ItemsControl.ItemTemplate> tag. Because that's why it's there; You are using it to set the ItemTemplate property of the ItemsControl around it.

<ItemsControl ItemsSource="{Binding MachinistUnreportedOps}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding MultiJobOps}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock>
                            <Run Text="Op " />
                            <Run Text="{Binding JobOperation}" />
                        </TextBlock>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
  • Related