简体   繁体   English

WPF 删除 ListBox 中的项目并抛出 NullReferenceException 时崩溃

[英]WPF Crash when delete items in ListBox and throw NullReferenceException

all全部

My application sometimes crashes and throws an exception When I delete multiple items in ListBox.当我删除 ListBox 中的多个项目时,我的应用程序有时会崩溃并引发异常。

I delete items through the delete command in MenuItem of ContextMenu.我通过 ContextMenu 的 MenuItem 中的删除命令删除项目。

I can't reproduce this exception, it's very strange.我无法重现此异常,这很奇怪。

The log is:日志是:

‧ System.NullReferenceException: Object reference not set to an instance of an object.    
  at System.Windows.Controls.VirtualizingStackPanel.GetMaxChildArrangeLength(IList children, Boolean isHorizontal) 
  at System.Windows.Controls.VirtualizingStackPanel.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)    
  at System.Windows.Controls.ItemsPresenter.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.ScrollContentPresenter.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Control.ArrangeOverride(Size arrangeBounds)    
  at System.Windows.Controls.ScrollViewer.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Control.ArrangeOverride(Size arrangeBounds)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)    
  at System.Windows.Controls.ContentPresenter.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Control.ArrangeOverride(Size arrangeBounds)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)    
  at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)    
  at System.Windows.UIElement.Arrange(Rect finalRect)    
  at System.Windows.ContextLayoutManager.UpdateLayout()    
  at System.Windows.Interop.HwndSource.Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam)    
  at System.Windows.Interop.HwndSource.LayoutFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)    
  at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)    
  at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)    
  at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)    
  at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Xaml is: Xaml 是:

<ListBox ItemsSource="{Binding ImgList}" SelectedItem="{Binding SelectedImg}" Style="{StaticResource ListBoxScroll}" SelectionMode="Extended" Background="#FF353535" HorizontalContentAlignment="Stretch" SelectionChanged="ListBox_SelectionChanged" BorderBrush="{x:Null}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderThickness="0">
    <ListBox.ContextMenu>
        <ContextMenu>                            
           <MenuItem Header="Delete File" Command="{Binding DeleteImageFileCommand}"/>
        </ContextMenu>
    </ListBox.ContextMenu>
    <ListBox.Resources>
        <DataTemplate x:Key="ItemTemplate">
             <Border Height="117" Width="208" BorderBrush="#FF979797" BorderThickness="1" Margin="21,0,0,18">
                 <Grid>
                    <Label x:Name="Lab" Width="40" Height="20" Grid.Column="0" Content="{Binding Converter={StaticResource ItemToIndex}, Mode=OneWay, Path=., RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" FontSize="14"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Top" Padding="0" Panel.ZIndex="1" Background="White" BorderBrush="#FF353535" BorderThickness="1" Foreground="#FF011627" Margin="-1,-1,0,0"/>
                    <Image Grid.Column="1" Width="208" Source="{Binding SmallImg, Converter={StaticResource MatToBmp}, IsAsync=True}" Stretch="Uniform"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListBox.Resources>
</ListBox>

Does anyone know how this exception is being thrown?有谁知道这个异常是如何被抛出的? I hope someone can help me, Thanks!我希望有人能帮助我,谢谢!

Update: I add the converter code below, and binding is: <local:FilterIndexConverter x:Key="ItemToIndex"/>更新:我在下面添加转换器代码,绑定是:<local:FilterIndexConverter x:Key="ItemToIndex"/>

public class FilterIndexConverter : IValueConverter
{
    public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
    {
        ListBoxItem item = (ListBoxItem)value;
        ListBox listBox = ItemsControl.ItemsControlFromItemContainer(item) as ListBox;
        int index = (listBox.ItemsSource as RangeObservableCollection<ImageInformation>).IndexOf((value as ListBoxItem).Content as ImageInformation);
        return index + 1;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

What System.Windows.Controls.VirtualizingStackPanel.GetMaxChildArrangeLength(IList children, Boolean isHorizontal) Means: System.Windows.Controls.VirtualizingStackPanel.GetMaxChildArrangeLength(IList children, Boolean isHorizontal) 的意思是:

The listbox has a VirtualizingStackPanel which is used to virtualise it's items.列表框有一个 VirtualizingStackPanel 用于虚拟化它的项目。 To do this it needs to decide what's going to fit in it.为此,它需要决定将要放入其中的内容。

WPF has a measure arrange mechanism which it uses to decide on what space everything needs. WPF 有一个度量安排机制,它用它来决定一切需要什么空间。 It looks at each thing in say a panel and asks what space it would like, then it looks at what constraints there are on it and decides what it can have as a measurement.它会查看面板中的每一件东西并询问它想要什么空间,然后它会查看它上面有哪些限制并决定它可以具有什么作为测量值。 It then arranges everything.然后它会安排一切。 Then renders.然后渲染。

https://learn.microsoft.com/en-us/do.net/desktop/wpf/advanced/layout?view.netframeworkdesktop-4.8#LayoutSystem_Overview https://learn.microsoft.com/en-us/do.net/desktop/wpf/advanced/layout?view.netframeworkdesktop-4.8#LayoutSystem_Overview

GetMaxChildArrangeLength is pretty obviously deciding how many items it will be able to fit in the viewport. GetMaxChildArrangeLength 非常明显地决定了它能够在视口中容纳多少项目。

You have this error because when it comes to one of those things it's trying to arrange, it gets null.你有这个错误是因为当涉及到它试图安排的其中一件事情时,它得到 null。

You do not seem to be able to reproduce this error.您似乎无法重现此错误。

Any fix is therefore going to have to be somewhat speculative.因此,任何修复都必须具有一定的推测性。 A guess.一个推测。

My guess is one or both of your converters are too complicated.我猜你的一个或两个转换器太复杂了。 Maybe that index converter is being called on something is actually virtualised and doesn't have a container.也许正在调用的索引转换器实际上是虚拟化的并且没有容器。

It could also / alternatively be your image converter MatToBmp causing this.它也可能/或者是您的图像转换器 MatToBmp 造成的。

I can't see the source to that but I'm guessing it's an expensive process because you made it async.我看不到它的来源,但我猜这是一个昂贵的过程,因为你让它异步了。

My suggestion is to make both these do less work.我的建议是让这两者做更少的工作。 Make them simpler or obviate them.使它们更简单或避免它们。

You can get item index much easier by setting AlternationCount high - to like 10,0000 and bind to AlternationIndex.通过将 AlternationCount 设置为 10,0000 并绑定到 AlternationIndex,您可以更轻松地获得项目索引。 Add 1.加1。

    {Binding
     RelativeSource={RelativeSource Mode=TemplatedParent}, 
     Path=(ItemsControl.AlternationIndex)}

Or alternatively expose an index int from your viewmodel and recalculate.或者从您的视图模型中公开一个索引 int 并重新计算。

Similarly, give that image a fixed height to cut down on measure arrange in each template.同样,给该图像一个固定的高度以减少每个模板中的尺寸排列。

Reduce the work MatToBmp is doing.减少 MatToBmp 正在做的工作。 Build bitmapsource in advance or something.提前构建位图源什么的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM