1

In my WPF App, I want to have several items that are generated by the user on runtime. These are from different classes and hence, my original idea was to add them to different Observable Collections and then use them as ItemsSources od different ItemsControls. However, WPF gives me the error System.InvalidOperationException: Items collection must be empty before using ItemsSource. I'm not a WPF expert, but the answer to THIS SO question seems to indicate that I can only have 1 ItemsControl.

THIS SO question indicates that maybe I should use the CompositeCollection Class, but unlike in the cited question, I have several completely different Observable Collections for completely different tasks.

Here is the relevant part of my XAML.CS with two Collections: 1 of a custom Interface type and 1 of custom Class type

 public MainWindow()
    {           
        InitializeComponent();          
        DefaultWindowDefinition.ItemsSource = ProcessElements = new ObservableCollection<IProcessSimulator>();
        PathControl.ItemsSource = PathElements = new ObservableCollection<VisualPath>();           
    }

And here is the relevant part of the XAML I tried to use:

<Grid           x:Name="MainGrid"
                Background="{StaticResource Alternating}"
                MouseLeftButtonUp="grid_MouseLeftButtonUp"
                ShowGridLines="True">
    <ItemsControl   Name="DefaultWindowDefinition"
                    ItemsSource="{Binding ProcessElements}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
               <!--HERE IS A LONG LIST OF ELEMENTS-->
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
               <!--TEMPLATE FOR THE 1ST ITEMSCONTROL-->
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemContainerStyle>
            <Style>
                <!--STYLE PROPERTIES FOR THE 1ST ITEMSCONTROL-->
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
    <ItemsControl Name="PathControl"
                    ItemsSource="{Binding PathElements}">
        <DataTemplate>
            <!--HERE IS A  LIST OF OTHER TYPE OFELEMENTS-->
        </DataTemplate>
    </ItemsControl>
</Grid>

How should I approach this problem or rather, what C#/WPF element should I use? A reference and some words of simple explanation is more than enough, I can google the rest myself, I just don't know, what to look for really.

Community
  • 1
  • 1
oneManArmin
  • 606
  • 6
  • 24
  • One thing I see that is wrong is that you don't need to bind `ItemsSource` in XAML, and also set it in the constructor. Setting just the member properties (`ProcessElements` and `PathElements`) should be enough. That might be causing the exception. If that isn't it, what line throws the exception? – Andy Feb 07 '17 at 15:32
  • That was not the source of the problems, but setting the ItemsSource _only_ in the Code Behind seems to work, so thank you for pointing this out! – oneManArmin Feb 07 '17 at 16:20

2 Answers2

1

You should set the ItemTemplate property of the "PathControl" to your DataTemplate:

    <ItemsControl Name="PathControl" ItemsSource="{Binding PathElements}">
        <ItemsControl.ItemTemplate> <!-- NOTE THIS -->
            <DataTemplate>
                <!--HERE IS A  LIST OF OTHER TYPE OFELEMENTS-->
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

If you omit the <ItemsControl.ItemTemplate> element, you are adding a DataTemplate to the Items collection of the ItemsControl and you can't also set its ItemsSource property.

Trying to do so will results in an System.InvalidOperationException exception being thrown with the error message you are getting.

It is perfectly fine for several ItemsControl to bind to the same source collection.

mm8
  • 163,881
  • 10
  • 57
  • 88
0

It seems like you are setting the ItemsSource twice. Once in the code behind and once in the XAML. Remove the code behind that sets the Items source and just initialize the observable collections. The XAML should take care of binding to the collections.

Josh
  • 10,352
  • 12
  • 58
  • 109
  • Well, I do define it twice, once in Code Behind: PathControl.ItemsSource = PathElements = new ObservableCollection(); and once in XAML: BUT the funny thing is that I was using my first Observable collection the **very same** way without any errors, I declared in once in Code Behind, then once in XAML. In fact, if I declare them **only** in XAML nothing works. This might very well be my VS, because it doesn't even recognise XAML, so I worked w/o color coding so far...Time to reinstall. – oneManArmin Feb 07 '17 at 15:55