@@ -92,7 +92,17 @@ public void HandleItemChange()
9292 HookupItemChangeListener ( null , Item ) ;
9393 UpdateExpansionState ( ) ;
9494 ReevaluateSelection ( ) ;
95- CanDrag = Item ? . GetType ( ) . GetProperty ( "Path" ) ? . GetValue ( Item ) is string path && Path . IsPathRooted ( path ) ;
95+
96+ if ( Item is IDraggableSidebarItemModel draggableItem )
97+ {
98+ CanDrag = IsValidDropPath ( draggableItem . DropPath ) ;
99+ UseReorderDrop = ! IsGroupHeader && CanDrag && draggableItem . IsReorderDropItem ;
100+ }
101+ else
102+ {
103+ CanDrag = false ;
104+ UseReorderDrop = false ;
105+ }
96106 }
97107
98108 private void HookupOwners ( )
@@ -138,32 +148,51 @@ private void HookupItemChangeListener(ISidebarItemModel? oldItem, ISidebarItemMo
138148 }
139149 }
140150
151+ private static bool IsValidDropPath ( string ? path )
152+ => path is not null && ( System . IO . Path . IsPathRooted ( path ) || path . StartsWith ( "Shell:" , StringComparison . OrdinalIgnoreCase ) ) ;
153+
141154 private void SidebarItem_DragStarting ( UIElement sender , DragStartingEventArgs args )
142155 {
143- if ( Item ? . GetType ( ) . GetProperty ( "Path" ) ? . GetValue ( Item ) is not string dragPath || ! Path . IsPathRooted ( dragPath ) )
156+ if ( Item is not IDraggableSidebarItemModel draggableItem || draggableItem . DropPath is not string dragPath || ! IsValidDropPath ( dragPath ) )
144157 return ;
145158
146- args . Data . SetData ( StandardDataFormats . Text , dragPath ) ;
147- args . Data . RequestedOperation = DataPackageOperation . Move | DataPackageOperation . Copy | DataPackageOperation . Link ;
148- args . Data . SetDataProvider ( StandardDataFormats . StorageItems , async request =>
159+ try
149160 {
150- var deferral = request . GetDeferral ( ) ;
151- try
161+ args . Data . SetData ( StandardDataFormats . Text , dragPath ) ;
162+ args . Data . RequestedOperation = DataPackageOperation . Move | DataPackageOperation . Copy | DataPackageOperation . Link ;
163+ args . Data . SetDataProvider ( StandardDataFormats . StorageItems , async request =>
152164 {
153- if ( Directory . Exists ( dragPath ) )
165+ var deferral = request . GetDeferral ( ) ;
166+ try
154167 {
155- var folder = await StorageFolder . GetFolderFromPathAsync ( dragPath ) ;
156- request . SetData ( new IStorageItem [ ] { folder } ) ;
168+ if ( Directory . Exists ( dragPath ) )
169+ {
170+ var folder = await StorageFolder . GetFolderFromPathAsync ( dragPath ) ;
171+ request . SetData ( new IStorageItem [ ] { folder } ) ;
172+ }
157173 }
158- }
159- catch
160- {
161- }
162- finally
163- {
164- deferral . Complete ( ) ;
165- }
166- } ) ;
174+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
175+ {
176+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale external drag payload while resolving StorageFolder in data provider." ) ;
177+ }
178+ finally
179+ {
180+ try
181+ {
182+ deferral . Complete ( ) ;
183+ }
184+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
185+ {
186+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale OLE deferral during drag data provider completion." ) ;
187+ }
188+ }
189+ } ) ;
190+ }
191+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
192+ {
193+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale OLE drag payload on DragStarting, cancelling drag." ) ;
194+ args . Cancel = true ;
195+ }
167196 }
168197
169198 private void SetFlyoutOpen ( bool isOpen = true )
@@ -394,21 +423,61 @@ private async void ItemBorder_DragOver(object sender, DragEventArgs e)
394423 IsExpanded = true ;
395424 }
396425
397- var insertsAbove = DetermineDropTargetPosition ( e ) ;
398- if ( insertsAbove == SidebarItemDropPosition . Center )
426+ DragOperationDeferral ? deferral = null ;
427+ try
399428 {
400- VisualStateManager . GoToState ( this , "DragOnTop" , true ) ;
429+ deferral = e . GetDeferral ( ) ;
401430 }
402- else if ( insertsAbove == SidebarItemDropPosition . Top )
431+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
403432 {
404- VisualStateManager . GoToState ( this , "DragInsertAbove" , true ) ;
433+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale OLE drag payload on GetDeferral during DragOver." ) ;
434+ VisualStateManager . GoToState ( this , "Normal" , true ) ;
435+ return ;
405436 }
406- else if ( insertsAbove == SidebarItemDropPosition . Bottom )
437+
438+ try
407439 {
408- VisualStateManager . GoToState ( this , "DragInsertBelow" , true ) ;
409- }
440+ var insertsAbove = DetermineDropTargetPosition ( e ) ;
410441
411- Owner ? . RaiseItemDragOver ( this , insertsAbove , e ) ;
442+ if ( Owner is not null )
443+ await Owner . RaiseItemDragOverAsync ( this , insertsAbove , e ) ;
444+
445+ if ( ! e . Handled || e . AcceptedOperation == DataPackageOperation . None )
446+ {
447+ VisualStateManager . GoToState ( this , "Normal" , true ) ;
448+ return ;
449+ }
450+
451+ if ( insertsAbove == SidebarItemDropPosition . Center )
452+ {
453+ VisualStateManager . GoToState ( this , "DragOnTop" , true ) ;
454+ }
455+ else if ( insertsAbove == SidebarItemDropPosition . Top )
456+ {
457+ VisualStateManager . GoToState ( this , "DragInsertAbove" , true ) ;
458+ }
459+ else if ( insertsAbove == SidebarItemDropPosition . Bottom )
460+ {
461+ VisualStateManager . GoToState ( this , "DragInsertBelow" , true ) ;
462+ }
463+ }
464+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
465+ {
466+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale external drag payload during sidebar DragOver processing." ) ;
467+ e . AcceptedOperation = DataPackageOperation . None ;
468+ VisualStateManager . GoToState ( this , "Normal" , true ) ;
469+ }
470+ finally
471+ {
472+ try
473+ {
474+ deferral ? . Complete ( ) ;
475+ }
476+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
477+ {
478+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale OLE deferral on DragOver completion." ) ;
479+ }
480+ }
412481 }
413482
414483 private void ItemBorder_ContextRequested ( UIElement sender , Microsoft . UI . Xaml . Input . ContextRequestedEventArgs args )
@@ -425,7 +494,16 @@ private void ItemBorder_DragLeave(object sender, DragEventArgs e)
425494 private void ItemBorder_Drop ( object sender , DragEventArgs e )
426495 {
427496 UpdatePointerState ( ) ;
428- Owner ? . RaiseItemDropped ( this , DetermineDropTargetPosition ( e ) , e ) ;
497+ try
498+ {
499+ Owner ? . RaiseItemDropped ( this , DetermineDropTargetPosition ( e ) , e ) ;
500+ }
501+ catch ( Exception ex ) when ( DragDropExceptionHelper . IsExpectedStaleDragData ( ex ) )
502+ {
503+ DragDropExceptionHelper . LogStaleDrag ( ex , "Stale external drag payload during sidebar Drop, drop discarded." ) ;
504+ e . AcceptedOperation = DataPackageOperation . None ;
505+ e . Handled = true ;
506+ }
429507 }
430508
431509 private SidebarItemDropPosition DetermineDropTargetPosition ( DragEventArgs args )
0 commit comments