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

时间:2014-04-03 10:19:26

标签: 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>

使用以下方式设置样式:

<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>

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

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

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

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

似乎在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: 

抱歉代码转储,但我不知道这段代码导致错误的部分,因为它只是抛出没有位置的错误,我相当肯定与{{{ 1}},如果没有RowDetails这没有问题,但是我不能为我的生活找出正在发生的事情。

另外,如果有人可以让我知道如何追踪这类错误?

编辑:

两件事。

删除行RowDetails允许应用程序无异常地运行,但显然从未显示详细信息行。

其次,注释掉DataGrid行样式中的RowDetailsVisibilityMode="VisibleWhenSelected"也具有允许它运行的相同效果,因此它必须与此类似,但是该代码直接来自Microsoft示例。

2 个答案:

答案 0 :(得分:17)

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

添加 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>

答案 1 :(得分: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>

显然,只要我将数据网格移动到样式表并使用它工作的ItemTemplate绑定它,就不能直接在xaml页面中为集合定义数据窗口。

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

我认为它抱怨的itemcollection是包含views控件的那个,并且它在运行时在单行内创建多个元素时会出现问题。