nullreferenceexception when dragging things inside a RadListBox

4 posts, 0 answers
  1. Andrey
    Andrey avatar
    1 posts
    Member since:
    Mar 2018

    Posted 22 Mar 2018 Link to this post

    So, I have a RadListBox that I have set up to reorder items when the user drags one list box item in between two others. Its xaml looks a little something like this:

    <tk:RadListBox Width="150"
        MaxHeight="700"
        VerticalAlignment="Top"
        VerticalContentAlignment="Top"
        tk:DragDropManager.AllowCapturedDrag="True"
        tk:DragDropManager.AllowDrag="True"
        AllowDrop="True"
        Background="Transparent"
        ItemContainerStyle="{StaticResource AttachmentDragItemStyle}"
        ItemTemplateSelector="{StaticResource ThumbnailTemplateSelector}"
        ItemsSource="{Binding Attachments}"
        ScrollViewer.CanContentScroll="False"
        ScrollViewer.HorizontalScrollBarVisibility="Disabled"
        ScrollViewer.VerticalScrollBarVisibility="Auto"
        SelectedItem="{Binding SelectedAttachment, Mode=TwoWay}">
         <tk:RadListBox.ItemsPanel>
               <ItemsPanelTemplate>
                      <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" />
                </ItemsPanelTemplate>
         </tk:RadListBox.ItemsPanel>
          <tk:RadListBox.DragDropBehavior>
                 <behaviors:ListBoxDragDropBehaviorEx />
          </tk:RadListBox.DragDropBehavior>
          <tk:RadListBox.DragVisualProvider>
                 <tk:ScreenshotDragVisualProvider />
          </tk:RadListBox.DragVisualProvider>
           <tk:RadListBox.DropVisualProvider>
                  <tk:LinearDropVisualProvider />
           </tk:RadListBox.DropVisualProvider>
    </tk:RadListBox>

     

    with the extended drag drop behavior being:

    public class ListBoxDragDropBehaviorEx : ListBoxDragDropBehavior
    {
        public override void DragDropCanceled(DragDropState state)
        {
            //base.DragDropCanceled(state);
        }
     
        protected override IEnumerable<object> CopyDraggedItems(DragDropState state)
        {
            //return base.CopyDraggedItems(state);
            return new List<object>();
        }
     
        public override void Drop(DragDropState state)
        {//implement some custom logic here
            //Do not call -> base.Drop(state);
            try
            {
                if (state.IsSameControl)
                {
                    if (state.InsertIndex < 0)
                        return;
     
                    if (state.DraggedItems != null)
                    {
                        foreach (var item in state.DraggedItems)
                        {
                            BaseEntity obj = item as BaseEntity;
                            if (obj == null)
                                continue;
                            var index = state.SourceItemsSource.IndexOf(obj);
                            if (index >= 0)
                            {
                                state.SourceItemsSource.Remove(obj);
                                state.SourceItemsSource.Insert(state.InsertIndex, obj);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                MessageBoxUtil.ShowMessageBox("Drag & Drop error occurred", "Unable to reorder");
            }           
        }
     
        public override void DragDropCompleted(DragDropState state)
        {
            try
            {
                base.DragDropCompleted(state);
            }
            catch (Exception e)
            {
                MessageBoxUtil.ShowMessageBox("Drag & Drop error occurred", "Unable to reorder");
            }
        }
    }

     

    Now, this works beautifully... when it doesn't crash. But occasionally, if the user decides to perform a crazy mouse seizure and too many drag and drops are issued too quickly, a nullreference exception will be thrown with this stack trace:

     

       at Telerik.Windows.Controls.RadListBoxDragDropHelper.Drop(FrameworkElement dropTarget, FrameworkElement dropItemsControl, Object data, Type itemType)
       at Telerik.Windows.DragDrop.Behaviors.DragDropHelper`2.Drop(Object sender, DragEventArgs e)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at Telerik.Windows.DragDrop.DragDropManager.DelegateHelper.OnDragEventHandler(Object sender, DragEventArgs e)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.OleDropTarget.RaiseDragEvent(RoutedEvent dragEvent, Int32 dragDropKeyStates, Int32& effects, DependencyObject target, Point targetPoint)
       at System.Windows.OleDropTarget.MS.Win32.UnsafeNativeMethods.IOleDropTarget.OleDrop(Object data, Int32 dragDropKeyStates, Int64 point, Int32& effects)
       at MS.Win32.UnsafeNativeMethods.DoDragDrop(IDataObject dataObject, IOleDropSource dropSource, Int32 allowedEffects, Int32[] finalEffect)
       at System.Windows.OleServicesContext.OleDoDragDrop(IDataObject dataObject, IOleDropSource dropSource, Int32 allowedEffects, Int32[] finalEffect)
       at System.Windows.DragDrop.OleDoDragDrop(DependencyObject dragSource, DataObject dataObject, DragDropEffects allowedEffects)
       at System.Windows.DragDrop.DoDragDrop(DependencyObject dragSource, Object data, DragDropEffects allowedEffects)
       at Telerik.Windows.DragDrop.DragDropManager.DoDragDrop(DependencyObject dragSource, Object data, DragDropEffects allowedEffects, DragDropKeyStates initialKeyState, Object dragVisual, Point relativeStartPoint, Point dragVisualOffset)
       at Telerik.Windows.DragDrop.DragInitializer.StartDrag()
       at Telerik.Windows.DragDrop.DragInitializer.StartDragPrivate(UIElement sender)
       at Telerik.Windows.DragDrop.DragInitializer.DragSourceOnMouseMove(Object sender, MouseEventArgs e)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.MouseDevice.Synchronize()
       at System.Windows.Input.MouseDevice.ChangeMouseCapture(IInputElement mouseCapture, IMouseInputProvider providerCapture, CaptureMode captureMode, Int32 timestamp)
       at System.Windows.Input.MouseDevice.Capture(IInputElement element, CaptureMode captureMode)
       at Telerik.Windows.DragDrop.DragInitializer.DragSourceMouseLeave(Object sender, MouseEventArgs e)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
       at System.Windows.ReverseInheritProperty.OnOriginValueChanged(DependencyObject oldOrigin, DependencyObject newOrigin, IList`1 otherOrigins, DeferredElementTreeState& oldTreeState, Action`2 originChangedAction)
       at System.Windows.Input.MouseDevice.ChangeMouseOver(IInputElement mouseOver, Int32 timestamp)
       at System.Windows.Input.MouseDevice.PreNotifyInput(Object sender, NotifyInputEventArgs e)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
       at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
       at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at System.Windows.Interop.HwndSource.InputFilterMessage(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)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Window.ShowHelper(Object booleanBox)
       at System.Windows.Window.ShowDialog()

    ^ This is the point where the window opens, so obviously there is no code between here and the crash that I have control of. I am wondering why this happens sometimes and what can be done to fix this? I see no way to prevent this crash as it all seems to be happening inside telerik code. Please advise. 

  2. Dilyan Traykov
    Admin
    Dilyan Traykov avatar
    1031 posts

    Posted 23 Mar 2018 Link to this post

    Hello Andrey,

    I tried to reproduce the aforementioned exception at my end using the code you provided, but was, unfortunately, unable to do so. I've attached the project I used in the process to my reply for your reference. Could you please have a look at it and let me know what modifications I can make to it in order to replicate the issue?

    Thank you in advance for your cooperation on the matter.

    Regards,
    Dilyan Traykov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  3. Andrey
    Andrey avatar
    2 posts
    Member since:
    Dec 2017

    Posted 23 Mar 2018 Link to this post

    Ugh... you guys aren't gonna believe this. So I just "fixed" it myself, and it is the most mind-bogglingly, heart-breakingly, earth-shatteringly stupid coding "solution" I've ever seen. Are you ready to hear this? ...I mean, really ready? Are you sure? ...No, I don't think you are.... you might want to sit down for this one first.

     

    So, I made a test project to reproduce this easier myself, and I also couldn't. This prompted me to take a deeper look at my own xaml... Turns out the problem line was this in the list box:

    ItemTemplateSelector="{StaticResource ThumbnailTemplateSelector}"

     

    Removing this one line makes the whole thing work. (And by "work" I mean "not crash", since it makes the list box items appear as just text of their .ToString()s, which of course isn't the desired result). But once I figured this out, I went inside, followed the trail of styles and templates, until eventually, I came to this inside the deepest ControlTemplate:

    <TextBlock Margin="0,-5,0,0"
        HorizontalAlignment="Right"
        VerticalAlignment="Top"
        Panel.ZIndex="1000"
        FontWeight="SemiBold"
        Padding="2">
        <TextBlock.Inlines>
            <Run Text="{Binding Size, Mode=OneWay}" />
        </TextBlock.Inlines>
    </TextBlock>

     

    My process of elimination eventually led to me removing this one textblock, which... magically fixed it. But of course this isn't quite ideal either, since I need this text to show up in my ListBoxItems. So what was my final solution? I "refactored" it into this:

    <TextBlock Margin="0,-5,0,0"
        HorizontalAlignment="Right"
        VerticalAlignment="Top"
        Panel.ZIndex="1000"
        FontWeight="SemiBold"
        Text="{Binding Size}"
        Padding="2"/>     
  4. Andrey
    Andrey avatar
    2 posts
    Member since:
    Dec 2017

    Posted 23 Mar 2018 in reply to Andrey Link to this post

    I'm still sitting here in stunned disbelief at how something like this even happens. How can simple TextBlock string binding semantics manage to break your entire drag and drop functions is beyond me... I'm leaving this whole experience with my faith in WPF badly shaken (and pretty much, Microsoft in general!)

     

    ...Needless to say, I'm not satisfied with this revelation at all, but I guess this will just have to be one of the great mysteries of our time. I'm just glad I was here to share it with someone.

     

    Cheers,

    - Andrey, a random WPF developer from Texas

Back to Top