将值添加到'System.Windows.Controls.ItemCollection'类型的集合中引发异常

Ben*_*Ben 12 c# wpf xaml exception

我的WPF应用程序出了问题,我不明白为什么.我远不是XAML的专家,我不明白这个错误,甚至代码的哪一部分都在抛出错误.

我有以下观点:

<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>
Run Code Online (Sandbox Code Playgroud)

使用以下方式设置样式:

<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>
Run Code Online (Sandbox Code Playgroud)

ViewModel是:

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
Run Code Online (Sandbox Code Playgroud)

BOE模型是一个简单的属性集合,包括:

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

再次付款一个简单的属性集合(这只是原型).

似乎在Caliburn Micro的OnStartup()方法中发生了异常,但我对此并不是100%肯定.它是:

  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: 
Run Code Online (Sandbox Code Playgroud)

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.

Chr*_*lle 18

您的问题是您没有以适当的方式定义列.

添加DataGrid.Columns标记

<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>
Run Code Online (Sandbox Code Playgroud)

  • 大多数使用GridView而不是DataGrid的人经常犯此错误。尝试将列而不是DataGrid.Columns集合添加到DataGrid的根元素。确实很难看到此错误,抛出的异常不是解释性的。 (2认同)

Ben*_*Ben 5

问题是这样的:

<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>
Run Code Online (Sandbox Code Playgroud)

显然,一旦我将datagrid移入样式表并使用有效的ItemTemplate对其进行绑定,就无法直接在xaml页面中为集合定义数据模板。

<ItemsControl ItemsSource="{Binding Payments}" ItemTemplate="{StaticResource PaymentItemTemplate}"/>
Run Code Online (Sandbox Code Playgroud)

我认为它所抱怨的itemcollection是包含视图控件的itemcollection,并且在运行时在单个行内创建多个元素时遇到了问题。