【问题标题】:DataGrid: An ItemsControl is inconsistent with its items sourceDataGrid:一个 ItemsControl 与其项目源不一致
【发布时间】:2013-10-25 03:09:20
【问题描述】:

当我在 DataGridViewModel 类中调用 FillGPLocationAndPrint 时,我得到了这个异常。下面是内部异常。发生的情况是硬编码的字典被传递到 FillGPLocationAndPrint,它从那里获取数据并将其放入绑定到 DataGrid 的 ItemsSource 属性的 GridData ObservableCollection。这会引发一个名为 CollectionChanged 的​​事件,该事件调用负责增加 DataGrid 高度属性和 MainWindow 高度属性的方法 GridDataChanged。基本上,随着行的增加和减少,网格和窗口高度会动态变化。

编辑:

进一步研究这个问题后,问题实际上是由

mainVm.WindowHeight += ROW_HEIGHT;

mainVm.WindowHeight -= ROW_HEIGHT;

声明。出于某种原因,它不喜欢改变窗口的高度。 mainVm 是代表主窗口的 ViewModel 的对象,WindowHeight 是绑定到主窗口中的 Height 属性的 double。

这里是 InnerException:

给开发者的信息(使用 Text Visualizer 阅读): 引发此异常的原因是名称为“grdData”的控件“System.Windows.Controls.DataGrid Items.Count:3”的生成器已接收到与 Items 集合的当前状态不一致的 CollectionChanged 事件序列。检测到以下差异: 累计计数 2 与实际计数 3 不同。[累计计数为(上次重置时的计数 + #Adds - 自上次重置以来的#Removes)。] 在索引 1:生成器的项目“{NewItemPlaceholder}”与实际项目“MechQualTestDataEntry.MechTestData”不同。

以下一个或多个来源可能引发了错误事件: System.Windows.Controls.ItemContainerGenerator System.Windows.Controls.ItemCollection System.Windows.Data.ListCollectionView System.Collections.ObjectModel.ObservableCollection`1[[MechQualTestDataEntry.MechTestData,MechQualTestDataEntry,版本=2.0.5.25,文化=中性,PublicKeyToken=null]] (加星标的来源被认为更有可能是问题的原因。)

最常见的原因是 (a) 更改集合或其计数而不引发相应事件,以及 (b) 引发具有不正确索引或项参数的事件。

异常的堆栈跟踪描述了不一致是如何被检测到的,而不是它们是如何发生的。要获得更及时的异常,请将生成器上的附加属性“PresentationTraceSources.TraceLevel”设置为值“High”并重新运行场景。一种方法是运行类似于以下的命令: System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator,System.Diagnostics.PresentationTraceLevel.High) 从立即窗口。这会导致检测逻辑在每个 CollectionChanged 事件之后运行,因此会降低应用程序的速度。

这是 DataGridViewModel 类(缩小):

    private const int GRID_HEIGHT_MAX = 390;
    private const int GRID_HEIGHT_MIN = 60;
    private const int ROW_HEIGHT = 22;
    private int prevRowCount;
    private double gridHeight;
    private MainWindowViewModel mainVm;
    private ObservableCollection<MechTestData> gridData;
    public DataGridViewModel(MainWindowViewModel mainVm)
    {
        this.mainVm = mainVm;
        GridHeight = GRID_HEIGHT_MIN;
        gridData = new ObservableCollection<MechTestData>();
        gridData.CollectionChanged += GridDataChanged;
    }
    public double GridHeight
    {
        get
        {
            return gridHeight;
        }
        set
        {
            gridHeight = value;
            OnPropertyChanged("GridHeight");
        }
    }
    public ObservableCollection<MechTestData> GridData
    {
        get
        {
            return gridData;
        }
        set
        {
            gridData = value;
            OnPropertyChanged("GridData");
        }
    }
    private void GridDataChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // If the grid height is less than or equal to
        // the maximum grid height
        if (gridHeight <= GRID_HEIGHT_MAX + 1)
        {
            // If we added rows, increase the grid height
            if (gridData.Count > prevRowCount)
            {
                GridHeight += ROW_HEIGHT;
                mainVm.WindowHeight += ROW_HEIGHT;
            }
        }

        // if the grid height is less than or equal to
        // the minimum grid height
        if (gridHeight > GRID_HEIGHT_MIN)
        {
            // If we deleted rows, decrease the grid height
            if (gridData.Count < prevRowCount)
            {
                GridHeight -= ROW_HEIGHT;
                mainVm.WindowHeight -= ROW_HEIGHT;
            }
        }

        // Cache the row count
        prevRowCount = gridData.Count;
    }
    public void FillGPLocationAndPrint(Dictionary<string, string> gpLocationToDiePrintMap)
    {
        foreach (KeyValuePair<string, string> map in gpLocationToDiePrintMap)
        {
            GridData.Add(new MechTestData(map.Key, map.Value));
        }
    }

ViewModelBase 类:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

XAML(减去所有其他组件):

<Window 
x:Class="MechQualTestDataEntry.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:MechQualTestDataEntry.Properties"
xmlns:wpftk="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:MechQualTestDataEntry"
Icon="/MechQualTestDataEntry;component/Resources/MechQualIcon.ico"
Title="MainWindow" 
Background="MidnightBlue"
ResizeMode="CanMinimize"
Height="{Binding WindowHeight}"
MinHeight="{Binding WindowHeight}"
MaxHeight="{Binding WindowHeight}"
MinWidth="700"
MaxWidth="1000"
Width="820">
<Window.Resources>
    <local:DateTimeConverter x:Key="DateTimeFormatter"/>
</Window.Resources>

    <!-- Data Grid -->
    <DataGrid
        DockPanel.Dock="Bottom"
        x:Name="grdData"
        CellStyle="{StaticResource cellStyle}"
        FontFamily="Verdana"
        Height="{Binding GridHeight}"
        Foreground="MidnightBlue"
        AutoGenerateColumns="False"
        RowHeight="22"
        CanUserAddRows="True"
        CanUserDeleteRows="True"
        CanUserReorderColumns="False"
        CanUserResizeColumns="False"
        CanUserResizeRows="False"
        CanUserSortColumns="True"
        ItemsSource="{Binding GridData}"
        SelectionUnit="CellOrRowHeader"
        SelectionMode="Extended">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}">
                <EventSetter 
                    Event="PreviewMouseLeftButtonDown" 
                    Handler="DataGridCell_PreviewMouseLeftButtonDown"/>
            </Style>
            <Style TargetType="{x:Type DataGridRowHeader}">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter Property="Background" Value="DeepSkyBlue" />
                        <Setter Property="BorderBrush" Value="MidnightBlue" />
                        <Setter Property="BorderThickness" Value="1" />
                        <Setter Property="Width" Value="15" />
                        <Setter Property="HorizontalContentAlignment" Value="Right" />
                        <Setter Property="VerticalContentAlignment" Value="Center" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="MidnightBlue" />
                        <Setter Property="BorderBrush" Value="DeepSkyBlue" />
                        <Setter Property="BorderThickness" Value="1" />
                        <Setter Property="Width" Value="15" />
                        <Setter Property="HorizontalContentAlignment" Value="Right" />
                        <Setter Property="VerticalContentAlignment" Value="Center" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>

            <!-- TO Number -->
            <DataGridTextColumn 
                Width="40"
                Binding="{Binding TONumber}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="TO #"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- GelPak Location -->
            <DataGridTextColumn 
                Width="60"
                Binding="{Binding GelPakLocation}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="GelPak Location"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Die Print -->
            <DataGridTextColumn 
                Width="60"
                Binding="{Binding DiePrint}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            Text="Die Print"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Wire Pull Test -->
            <DataGridTextColumn 
                Width="70"
                Binding="{Binding WirePullTestValue}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="Wire Pull Test"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Failure Mode -->
            <DataGridTextColumn 
                Width="84"
                Binding="{Binding FailureMode}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            Text="Failure Mode"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Ball Shear -->
            <DataGridTextColumn 
                Width="70"
                Binding="{Binding BallShearTestValue}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="Ball Shear Test"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Die Shear -->
            <DataGridTextColumn 
                Width="70"
                Binding="{Binding DieShearTestValue}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="Die Shear Test"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- InP Remaining -->
            <DataGridTextColumn 
                Width="70"
                Binding="{Binding InPRemaining}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="InP Remaining"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Test Result -->
            <DataGridTextColumn 
                Width="70"
                Binding="{Binding TestResult}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="Pass/Fail"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>

            <!-- Notes -->
            <DataGridTextColumn
                Width="*"
                Binding="{Binding Notes}">
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock
                            Style="{StaticResource tbkStyleGridHeader}"
                            TextWrapping="Wrap"
                            Text="Notes"/>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>

我们将不胜感激任何解决此问题的帮助。

问候,

凯尔

【问题讨论】:

  • 我想到的可能的快速解决方案:将有问题的代码放入Dispatcher.BeginInvoke()
  • 刚试过这个,它抛出了完全相同的异常。我输入: GridData.Add(new MechTestData(map.Key, map.Value));在调度程序调用方法中。
  • 我还想补充一点,我的原始解决方案在我的开发机器上完美运行,但是当我部署它时,我几乎在每台生产机器上都会遇到这个异常。所有生产机器都运行与我的开发机器相同的操作系统:安装了 .NET 4.0 的 Windows 7 Professional x64

标签: c# .net wpf data-binding datagrid


【解决方案1】:

我想我会回答这个问题,因为我发布这个问题已经有一段时间了。问题是 .NET 4.0 安装问题。我们在所有出现此问题的计算机上卸载并重新安装了该框架,并解决了该问题。

【讨论】:

    【解决方案2】:

    我的问题通过这种方法解决了。 转到 Visual Studio > 工具 > 选项 > 调试 > 数据绑定 > Vorbose。

    【讨论】:

    • 多么奇怪。这也解决了我完全相同的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    相关资源
    最近更新 更多