Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm having a problem with my WPF application, and i have no idea why. I'm far from an expert with XAML, and I don't understand this error, or even what part of the code is throwing the error.

I have the following view:

<DataGrid BorderThickness="0" Width="Auto" AutoGenerateColumns="False" AlternationCount="2"
          IsSynchronizedWithCurrentItem="True" AutomationProperties.AutomationId="PositionSummaryGrid" 
          ItemsSource="{Binding Path=BOEList}" RowDetailsVisibilityMode="VisibleWhenSelected">
    <DataGrid.Columns>
        <DataGridTextColumn Header="BOE Reference" Binding="{Binding Path=Reference}"/>
        <DataGridTextColumn Header="Account No" Binding="{Binding Path=AccountNo}"/>
        <DataGridTextColumn Header="LBL Invoice No" Binding="{Binding Path=InvoiceNo}"/>
        <DataGridTextColumn Header="Date Raised" Binding="{Binding Path=DateRaised}"/>
        <DataGridTextColumn Header="Value" Binding="{Binding Converter={StaticResource currencyConverter}, Path=Value}" Width="85"/>
        <DataGridTextColumn Header="Bank Charges" Binding="{Binding Converter={StaticResource currencyConverter}, Path=BankCharges}" Width="85"/>
        <DataGridTextColumn Header="Payment Due" Binding="{Binding Converter={StaticResource currencyConverter}, Path=PaymentDue}" Width="85"/>
        <DataGridTextColumn Header="Description" Binding="{Binding Path=Description}" Width="auto"/>
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Payments}">
                <DataGridTextColumn Header="Payment Date" Binding="{Binding PaymentDate}"/>
                <DataGridTextColumn Header="Payment Amount" Binding="{Binding Converter={StaticResource currencyConverter}, Path=PaymentAmount}"/>
            </DataGrid>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

Which is styled using the following:

<Style x:Key="DataGridScrollViewer" TargetType="{x:Type ScrollViewer}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                <Grid Background="{TemplateBinding Background}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <DockPanel Margin="{TemplateBinding Padding}">
                        <ScrollViewer DockPanel.Dock="Top"
                                      HorizontalScrollBarVisibility="Hidden"
                                      VerticalScrollBarVisibility="Hidden"
                                      Focusable="false">
                            <Border CornerRadius="4" Background="{StaticResource DefaultedBorderBrush}" Padding="4" Margin="0,4,0,4">
                                <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"/>
                            </Border>
                        </ScrollViewer>

                        <ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local"/>
                    </DockPanel>

                    <ScrollBar Name="PART_HorizontalScrollBar"
                        Orientation="Horizontal"
                        Grid.Row="1"
                        Maximum="{TemplateBinding ScrollableWidth}"
                        ViewportSize="{TemplateBinding ViewportWidth}"
                        Value="{TemplateBinding HorizontalOffset}"
                        Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                    <ScrollBar Name="PART_VerticalScrollBar"
                        Grid.Column="1"
                        Maximum="{TemplateBinding ScrollableHeight}"
                        ViewportSize="{TemplateBinding ViewportHeight}"
                        Value="{TemplateBinding VerticalOffset}"
                        Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="DataGridColumnHeaderGripper" TargetType="{x:Type Thumb}">
    <Setter Property="Width" Value="18"/>
    <Setter Property="Background" Value="#404040"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Border Padding="{TemplateBinding Padding}" Background="Transparent">
                    <Rectangle HorizontalAlignment="Center" Width="1" Fill="{TemplateBinding Background}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="{x:Type DataGridColumnHeader}" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Foreground" Value="#ffffff"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                <Grid>
                    <Border Name="HeaderBorder" BorderThickness="0,1,0,1" BorderBrush="{x:Null}" Background="{x:Null}" Padding="2,0,2,0">
                        <ContentPresenter Name="HeaderContent" Margin="0,0,0,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Margin="0,0,-9,0" Style="{StaticResource DataGridColumnHeaderGripper}" Foreground="#FFFFFFFF" Background="{x:Null}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" TargetName="PART_HeaderGripper" Value="{x:Null}"/>
                        <Setter Property="Foreground" TargetName="PART_HeaderGripper" Value="#FFFCFCFC"/>
                        <Setter Property="Background" TargetName="HeaderBorder" Value="{x:Null}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter TargetName="HeaderContent" Property="Margin" Value="1,1,0,0"/>
                        <Setter Property="Foreground" TargetName="PART_HeaderGripper" Value="#FFE0E0E0"/>
                        <Setter Property="Background" TargetName="PART_HeaderGripper" Value="{x:Null}"/>
                        <Setter Property="Background" TargetName="HeaderBorder" Value="{x:Null}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        <Setter Property="Background" TargetName="PART_HeaderGripper" Value="{x:Null}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="GridLinesVisibility" Value="None"/>
    <Setter Property="SelectionMode" Value="Extended"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGrid}">
                <Border Name="Border" BorderThickness="1" BorderBrush="{x:Null}" Background="{x:Null}">
                    <ScrollViewer Style="{DynamicResource DataGridScrollViewer}" Foreground="#FFFFFFFF">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </ScrollViewer>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="Border" Property="Background" Value="#AAAAAA"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="{x:Type DataGridRow}" TargetType="{x:Type DataGridRow}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Foreground" Value="#000000"/>
    <Setter Property="DetailsVisibility" Value="Collapsed"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridRow}">
                <Border Name="Border" Padding="2" SnapsToDevicePixels="true" CornerRadius="4" Margin="0,4,0,0">
                    <SelectiveScrollingGrid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>

                        <DataGridCellsPresenter Grid.Column="1"
                                         ItemsPanel="{TemplateBinding ItemsPanel}"
                                         SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

                        <DataGridDetailsPresenter  SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}"
                                            Grid.Column="1" Grid.Row="1"
                                            Visibility="{TemplateBinding DetailsVisibility}" />

                        <DataGridRowHeader SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"  Grid.RowSpan="2"
                                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}"/>
                    </SelectiveScrollingGrid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                        <Setter Property="Background" TargetName="Border"  Value="#A5FFFFFF"></Setter>
                    </Trigger>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                        <Setter Property="Background" TargetName="Border"  Value="#01FFFFFF"></Setter>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Background" TargetName="Border" Value="#99B4C6"/>
                        <Setter Property="Foreground" Value="#000000"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" TargetName="Border" Value="#c5d7e5"/>
                        <Setter Property="Foreground" Value="#000000"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="#000000"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>              
</Style>

<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid>
                    <Rectangle Fill="White" Opacity="0"></Rectangle>
                    <ContentPresenter HorizontalAlignment="Center"/> 
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The ViewModel is:

public class BoeListViewModel : Screen
{
    #region Fields
    private BOEManager _Manager;
    private ObservableCollection<BOE> _boeList;
    #endregion

    #region Properties
    public ObservableCollection<BOE> BOEList
    {
        get { return _boeList; }
        set
        {
            _boeList = value;
            NotifyOfPropertyChange(() => BOEList);
        }
    }

    public string Header
    {
        get { return "CURRENT BOES"; }
    }
    #endregion

    #region Constructor
    public BoeListViewModel()
    {
        this.DisplayName = "Current BOEs";
        _Manager = IoC.Get<BOEManager>();
        BOEList = _Manager.load();
    }
    #endregion

The BOE Model is a simple collection of properties including:

public ObservableCollection<Payment> Payments
{
    get { return _payments; }
    set
    {
        if (value != _payments)
        {
            _payments = value;
            NotifyOfPropertyChange(() => Payments);
        }
    }
}

With payment again a simple collection of Properties (this is just prototyping).

Exception appears to happen inside Caliburn Micro's OnStartup() method, but I'm not 100% sure about that. and it is:

  System.Windows.Markup.XamlParseException occurred
  HResult=-2146233087
  Message=Add value to collection of type 'System.Windows.Controls.ItemCollection' threw an exception.
  Source=PresentationFramework
  LineNumber=0
  LinePosition=0
  StackTrace:
       at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
       at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
       at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
       at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
       at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
       at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
       at System.Windows.FrameworkElement.ApplyTemplate()
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
       at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
       at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.ContextLayoutManager.UpdateLayout()
       at System.Windows.UIElement.UpdateLayout()
       at System.Windows.Interop.HwndSource.SetLayoutSize()
       at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
       at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
       at System.Windows.Window.SetRootVisual()
       at System.Windows.Window.SetRootVisualAndUpdateSTC()
       at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
       at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
       at System.Windows.Window.CreateSourceWindowDuringShow()
       at System.Windows.Window.SafeCreateWindowDuringShow()
       at System.Windows.Window.ShowHelper(Object booleanBox)
       at System.Windows.Window.Show()
       at Caliburn.Micro.WindowManager.ShowWindow(Object rootModel, Object context, IDictionary`2 settings) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.WPF\WindowManager.cs:line 75
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.
       Source=PresentationFramework
       StackTrace:
            at System.Windows.Controls.ItemCollection.CheckIsUsingInnerView()
            at System.Windows.Controls.ItemCollection.Add(Object newItem)
            at System.Xaml.Schema.XamlTypeInvoker.AddToCollection(Object instance, Object item)
            at MS.Internal.Xaml.Runtime.ClrObjectRuntime.Add(Object collection, XamlType collectionType, Object value, XamlType valueXamlType)
       InnerException: 

sorry for the code dump, but I have no real clue what part of this code is causing the error, as it just throws the error without a location, I'm fairly certain is has to do with the RowDetails, as without the RowDetails this works without an issue, however I cannot for the life of me work out what is going on.

Also, if someone could let me know how to track down these kind of error?

EDIT:

Two things.

Removing the line RowDetailsVisibilityMode="VisibleWhenSelected" allows the application to run without an exception, however obviously then the details row is never shown.

Secondly, commenting out the DataGridDetailsPresenter inside the DataGrid row style also has the same effect of allowing this to run, so it must be something with that, however that code is taken straight from Microsoft examples.

like image 339
Ben Avatar asked Apr 03 '14 10:04

Ben


Video Answer


2 Answers

Your problem is that you do not define your columns in a proper way.

Add a DataGrid.Columns tag

<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Payments}">
            <DataGrid.Columns> 
                <DataGridTextColumn Header="Payment Date" Binding="{Binding PaymentDate}"/>
                <DataGridTextColumn Header="Payment Amount" Binding="{Binding Converter={StaticResource currencyConverter}, Path=PaymentAmount}"/>
            </DataGrid.Columns> 
        </DataGrid>
    </DataTemplate>
</DataGrid.RowDetailsTemplate>
like image 85
Chrille Avatar answered Sep 25 '22 13:09

Chrille


The Problem was this:

<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Payments}">
            <DataGridTextColumn Header="Payment Date" Binding="{Binding PaymentDate}"/>
            <DataGridTextColumn Header="Payment Amount" Binding="{Binding Converter={StaticResource currencyConverter}, Path=PaymentAmount}"/>
        </DataGrid>
    </DataTemplate>
</DataGrid.RowDetailsTemplate>

Apparently you cannot define a datatemplate for a collection directly in the xaml page, as soon as i moved the datagrid into a style sheet and bound it using ItemTemplate it worked.

<ItemsControl ItemsSource="{Binding Payments}" ItemTemplate="{StaticResource PaymentItemTemplate}"/>

I assume the itemcollection it was complaining about was the one containing the views controls, and that it has issues creating multiple elements inside a single row at runtime.

like image 44
Ben Avatar answered Sep 25 '22 13:09

Ben