Search code examples
wpfxamlmvvmuser-controlsitemscontrol

ItemsControl of UserControls with ViewModels


I would like to do a very simple thing (I think) with XAML.

I want to show a list of usercontrols 'UserControl A' (with viewModels 'ViewModel A') in an ItemControl, hosted in a 'UserControl B'.

The 'ViewModel B' contains a property which is a observableCollection of 'UserControls A'.

In the Ctor of the 'userControls A', I've set :

Me.DataContext = New ViewModelA()

in the Ctor of the 'userControlB', I've set the same, but with a 'ViewModel B'.

The 'ViewModel A' contains two properties (Integer) 'Row' and 'Col'.

What I want is to bind each 'userControl A' and the values of 'Col' and 'Row' in a Grid hosted in 'UserControl B'.

Here is what I've done : UserControl B :

<ItemsControl ItemsSource="{Binding ListOfUserControl_A}" Margin="1.5">
            <ItemsPanelTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Grid.Column" Value="{Binding Col}" />
                    <Setter Property="Grid.Row" Value="{Binding Row}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:UserControl_A/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

The collection is properly filled before this process.

But in runtime I have this error (translated from French): "The Collection must be empty to use 'ItemsSource'".

An other error which I had before was that 'The itemTemplate and ItemTemplateSelector are not valid for UserControl_B'...

What am I doing wrong ?


Solution

  • You forgot to wrap ItemsPanelTemplate in ItemsControl.ItemsPanel tag. Without that ItemsControl treats ItemsPanelTemplate as an item and since you already set ItemsSource you get that error

    <ItemsControl ItemsSource="{Binding ListOfUserControl_A}" Margin="1.5">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>