When I make a call to FillGPLocationAndPrint in the DataGridViewModel class, I get this exception. Below is the inner exception. What happens is a hard coded Dictionary is passed into FillGPLocationAndPrint where it takes the data from there and puts it into the GridData ObservableCollection which is bound to the ItemsSource property of the DataGrid. This raises an event called CollectionChanged, which calls the method GridDataChanged which is responsible for increasing the DataGrid height property and the MainWindow height property. Basically, as rows are added and subtracted, the grid and window height change dynamically.
Edit:
After looking a little further into this issue, the problem is actually caused by the
mainVm.WindowHeight += ROW_HEIGHT;
and
mainVm.WindowHeight -= ROW_HEIGHT;
statements. For some reason, it does not like changing the height of the window. mainVm is an object that represents the ViewModel of the main window and WindowHeight is a double that is bound to the Height property in the main window.
Here is InnerException:
Information for developers (use Text Visualizer to read this): This exception was thrown because the generator for control 'System.Windows.Controls.DataGrid Items.Count:3' with name 'grdData' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection. The following differences were detected: Accumulated count 2 is different from actual count 3. [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).] At index 1: Generator's item '{NewItemPlaceholder}' is different from actual item 'MechQualTestDataEntry.MechTestData'.
One or more of the following sources may have raised the wrong events: System.Windows.Controls.ItemContainerGenerator System.Windows.Controls.ItemCollection System.Windows.Data.ListCollectionView System.Collections.ObjectModel.ObservableCollection`1[[MechQualTestDataEntry.MechTestData, MechQualTestDataEntry, Version=2.0.5.25, Culture=neutral, PublicKeyToken=null]] (The starred sources are considered more likely to be the cause of the problem.)
The most common causes are (a) changing the collection or its Count without raising a corresponding event, and (b) raising an event with an incorrect index or item parameter.
The exception's stack trace describes how the inconsistencies were detected, not how they occurred. To get a more timely exception, set the attached property 'PresentationTraceSources.TraceLevel' on the generator to value 'High' and rerun the scenario. One way to do this is to run a command similar to the following: System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator, System.Diagnostics.PresentationTraceLevel.High) from the Immediate window. This causes the detection logic to run after every CollectionChanged event, so it will slow down the application.
Here is the DataGridViewModel class (shrunk down):
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 class:
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 (minus all the other components):
<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>
Any help in solving this problem will much appreciated.
Regards,
Kyle
Dispatcher.BeginInvoke(). - Federico Berasategui