And if it is, what control would be the best bet? DataGrid that has the virtualization or something else? This happens very very rarely so trial and error is not an option. Portion of my xaml and converter used is in the end.
This happens sometimes (maybe 1/1000?) when DataGrid's itemssource (ICollectionView) is refreshed.
2017-10-06 09:00:35: myapp.exe Error: 0 : Unhandled exception. System.ArgumentException: Height must be non-negative.
at System.Windows.Rect.set_Height(Double value)
at System.Windows.Controls.VirtualizingStackPanel.ExtendViewport(IHierarchicalVirtualizationAndScrollInfo virtualizationInfoProvider, Boolean isHorizontal, Rect viewport, VirtualizationCacheLength cacheLength, VirtualizationCacheLengthUnit cacheUnit, Size stackPixelSizeInCacheBeforeViewport, Size stackLogicalSizeInCacheBeforeViewport, Size stackPixelSizeInCacheAfterViewport, Size stackLogicalSizeInCacheAfterViewport, Size stackPixelSize, Size stackLogicalSize, Int32& itemsInExtendedViewportCount)
at System.Windows.Controls.VirtualizingStackPanel.IsExtendedViewportFull()
at System.Windows.Controls.VirtualizingStackPanel.ShouldItemsChangeAffectLayoutCore(Boolean areItemChangesLocal, ItemsChangedEventArgs args)
at System.Windows.Controls.VirtualizingPanel.OnItemsChangedInternal(Object sender, ItemsChangedEventArgs args)
at System.Windows.Controls.Panel.OnItemsChanged(Object sender, ItemsChangedEventArgs args)
at System.Windows.Controls.ItemContainerGenerator.OnItemAdded(Object item, Int32 index)
at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
at System.Collections.ObjectModel.ReadOnlyObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at MS.Internal.Data.CollectionViewGroupInternal.Insert(Object item, Object seed, IComparer comparer)
at MS.Internal.Data.CollectionViewGroupRoot.AddToSubgroup(Object item, LiveShapingItem lsi, CollectionViewGroupInternal group, Int32 level, Object name, Boolean loading)
at MS.Internal.Data.CollectionViewGroupRoot.AddToSubgroups(Object item, LiveShapingItem lsi, CollectionViewGroupInternal group, Int32 level, Boolean loading)
at System.Windows.Data.ListCollectionView.AddItemToGroups(Object item, LiveShapingItem lsi)
at System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(NotifyCollectionChangedEventArgs args, Int32 adjustedOldIndex, Int32 adjustedNewIndex)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at MS.Internal.Data.EnumerableCollectionView.LoadSnapshotCore(IEnumerable source)
at MS.Internal.Data.EnumerableCollectionView.LoadSnapshot(IEnumerable source)
at System.Windows.Data.CollectionView.RefreshInternal()
XAML:
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Name="SelectedObjectsRowDefinition">
<RowDefinition.Height>
<MultiBinding Converter="{StaticResource GridRowHeightConverter}">
<Binding ElementName="SelectedObjectsExpander" Path="IsExpanded" />
<Binding Path="IsSelectedObjectsVisible" />
<Binding ElementName="SelectedObjectsGrid" Path="Items.Count" />
</MultiBinding>
</RowDefinition.Height>
</RowDefinition>
<RowDefinition Name="SelectedSwitchesRowDefinition">
<RowDefinition.Height>
<MultiBinding Converter="{StaticResource GridRowHeightConverter}">
<Binding ElementName="SelectedSwitchesExpander" Path="IsExpanded" />
<Binding Path="IsSelectedSwitchesVisible" />
<Binding ElementName="SelectedSwitchesGrid" Path="Items.Count" />
</MultiBinding>
</RowDefinition.Height>
</RowDefinition>
<RowDefinition Name="SelectionsRowDefinition">
<RowDefinition.Height>
<MultiBinding Converter="{StaticResource GridRowHeightConverter}">
<Binding ElementName="SelectionsExpander" Path="IsExpanded" />
<Binding Path="IsSelectionSetsVisible" />
<Binding ElementName="SelectionSetsGrid" Path="Items.Count" />
</MultiBinding>
</RowDefinition.Height>
</RowDefinition>
</Grid.RowDefinitions>
<Expander Grid.Row="0" Header="{DynamicResource XpStrSelectedObjects}" x:Name="SelectedObjectsExpander" AutomationProperties.AutomationId="SelectedObjectsExp"
IsExpanded="{Binding IsSelectedObjectsExpanded}" Visibility="{Binding IsSelectedObjectsVisible, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid Margin="15,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Background="White"
Visibility="{Binding ShowSelectedObjectsInfoPanel, Converter={StaticResource BoolToVisibilityConverter}}" Margin="0,0,4,0">
<StackPanel Margin="0,0,4,0">
<TextBlock Text="{Binding SelectedObjectsInfoPanelText}"
FontStyle="Italic" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button HorizontalAlignment="Center" Content="{StaticResource NisStrShowAnyway}"
Visibility="{Binding IsFetchObjectsAnywayVisible, Converter={StaticResource BoolToVisibilityConverter}}"
Command="{ui:CommandHandler FetchObjectsAnyway}"
AutomationProperties.AutomationId="ShowAnywayBtn"/>
</StackPanel>
</Grid>
<DataGrid Name="SelectedObjectsGrid" AutomationProperties.AutomationId="SelectedObjectsDgd"
Visibility="{Binding ShowSelectedObjectsInfoPanel, Converter={StaticResource BoolNegationToVisibilityConverter}}"
ItemsSource="{Binding SelectedObjectItems}"
SelectionMode="Extended"
CanUserAddRows="False"
AutoGenerateColumns="False"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.VirtualizationMode="Standard"
VerticalAlignment="Top"
IsReadOnly="True"
Grid.Row="0" Margin="0,0,4,0">
Convert-method of IMultivalueConverter used in XAML above:
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
bool isExpanded = (bool)values[0];
bool isVisible = (bool)values[1];
int itemsCount = (int)values[2];
if (!isVisible || !isExpanded || itemsCount == 0)
return System.Windows.GridLength.Auto;
else
return new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
}
catch (Exception)
{
return new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
}
}