如果是的话,最好的选择是什么?具有虚拟化或其他功能的 DataGrid?这种情况很少发生,所以试错不是一种选择。我使用的 xaml 和转换器的一部分在最后。
当刷新 DataGrid 的 itemssource (ICollectionView) 时,有时会发生这种情况(可能是 1/1000?)。
2017-10-06 09:00:35:myapp.exe 错误:0:未处理的异常。System.ArgumentException:高度必须为非负数。
在 System.Windows.Rect.set_Height(双值)
在 System.Windows.Controls.VirtualizingStackPanel.ExtendViewport(IHierarchicalVirtualizationAndScrollInfo 虚拟化信息提供者,布尔是水平的,矩形视口,VirtualizationCacheLength 缓存长度,VirtualizationCacheLengthUnit 缓存单元,大小 stackPixelSizeInCacheBeforeViewport,大小 stackLogicalSizeInCacheBeforeViewport,大小 stackPixelSizeInCacheAfterViewport,大小 stackLogicalSizeInCacheAfterViewport,大小 stackPixelSize&,InxtendedViewport 大小)
在 System.Windows.Controls.VirtualizingStackPanel.IsExtendedViewportFull()
在 System.Windows.Controls.VirtualizingStackPanel.ShouldItemsChangeAffectLayoutCore(布尔 areItemChangesLocal,ItemsChangedEventArgs 参数)
在 System.Windows.Controls.VirtualizingPanel.OnItemsChangedInternal(对象发送者,ItemsChangedEventArgs 参数)
在 System.Windows.Controls.Panel.OnItemsChanged(对象发送者,ItemsChangedEventArgs args)
在 System.Windows.Controls.ItemContainerGenerator.OnItemAdded(对象项,Int32 索引)
在 System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(对象发送者,NotifyCollectionChangedEventArgs 参数)
在 System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(对象发送者,EventArgs e,类型 managerType)
在 System.Windows.WeakEventManager.DeliverEvent(对象发送者,EventArgs 参数)
在 System.Collections.ObjectModel.ReadOnlyObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs 参数)
在 System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
在 System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 索引,T 项)
在 MS.Internal.Data.CollectionViewGroupInternal.Insert(对象项,对象种子,IComparer 比较器)
在 MS.Internal.Data.CollectionViewGroupRoot.AddToSubgroup(对象项,LiveShapingItem lsi,CollectionViewGroupInternal 组,Int32 级别,对象名称,布尔加载)
在 MS.Internal.Data.CollectionViewGroupRoot.AddToSubgroups(对象项,LiveShapingItem lsi,CollectionViewGroupInternal 组,Int32 级别,布尔加载)
在 System.Windows.Data.ListCollectionView.AddItemToGroups(对象项,LiveShapingItem lsi)
在 System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(NotifyCollectionChangedEventArgs 参数,Int32 调整的OldIndex,Int32 调整的新索引)
在 System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
在 System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 索引,T 项)
在 MS.Internal.Data.EnumerableCollectionView.LoadSnapshotCore(IEnumerable 源)
在 MS.Internal.Data.EnumerableCollectionView.LoadSnapshot(IEnumerable 源)
在 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">
上面 XAML 中使用的 IMultivalueConverter 的转换方法:
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);
}
}