Kidiskidvogingogin Kidiskidvogingogin - 2 months ago 56
C# Question

How to bind nested ItemsControl ItemsSource to an ObservableCollection nested within parent ItemControl's bound item

I have an

ItemsControl
that is bound to an
ObservableCollection
. Inside of that
ItemsControl
I have another
ItemsControl
which is bound to another
ObservableCollection
contained within the objects of the outermost
ItemsControl
's ObservableCollection. When the XAML parser attempts to build the innermost
ItemsControl
's
DataTemplate
there is an exception thrown


System.Windows.Markup.XamlParseException: Add value to collection of
type 'System.Windows.Controls.ItemCollection' threw an exception.


and the inner exception is:


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


To make it a little more clear, here is my XAML Structure:

<Grid DataContext="{Binding ...Name of object holding ObservableCollection here}">
<ItemsControl Name="FilterItemsHolder" Grid.Row="1"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Margin="10,10,10,10" MinWidth="200"
Background="#151515"
ItemsSource="{Binding CheckedFilterColumns}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid MaxHeight="100">
<ItemsControl Name="FilterSelectionsHolder"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Margin="10,10,10,10" MaxHeight="50"
ItemsSource="{Binding FilterSelections}">
<DataTemplate>
<rb:RBFilterOptions x:Name="FilterOptions" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</DataTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>


The class structure of the DataBound items is:

public class ClassThatHoldsCollections...
{
... some other properties
public ObservableCollection<RBDataColumn> CheckedFilterColumns { get; set; } //bound to outermost ItemsControl's (Name="FilterItemsHolder") ItemsSource

public ClassThatHoldsCollections...()
{
...initialize property values...
CheckedFilterColumns = new ObservableCollection<RBDataColumn>();
}
}
public class RBDataColumn
{
...some properties

public ObservableCollection<RBDataColumnFilterSelection> FilterSelections { get; set; } //bound to innermost ItemsControl's (Name="FilterSelectionsHolder") ItemsSource

public RBDataColumn()
{
...initialize property values...
FilterSelections = new ObservableCollection<RBDataColumnFilterSelection>();
}
}


Oddly enough if I comment out the
<DataTemplate>...</DataTemplate>
the exception is no longer thrown. If I leave the
<DataTemplate></DataTemplate>
tags and comment out only the referenced user control within
<rb:RBFilterOptions.../>
the exception is still thrown which means that it cannot be the underlying user control that is causing the issue.

It seems to me that the XAML parser that builds the window is trying to add the inner
ItemsControl
's values while still accessing the outermost
ItemsControl
's.

MY QUESTION, IN TWO PARTS, IS:


  1. Why is the exception thrown?

  2. Is there a way to have nested
    ItemsControl
    s whose
    ItemsSource
    properties are pointed to nested
    ObservableCollections
    ?


Answer

The clue is in the error message i.e. there's something wrong with your XAML. Specifically, you've declared your inner DataTemplate as a direct child of FilterSelectionsHolder, so the XAML parser thinks you're adding it as a collection item rather than a template. Try wrapping the inner DataTemplate in a ItemsControl.ItemTemplate block.

Sometimes it just takes a second set of eyes. ;)

Comments