TreeView Drop Event not triggering for its children TreeView items drag and drop.
Describe the bug
When using the TreeView object, the Drop event is not triggered correctly. It only works when hovering another TreeView item and putting back the dragged item at its original place.
When dropping an item on another item, or dragging an item and dropping it to a new location, the drop event is never triggered.
Steps to reproduce the bug
Scenario 1 (triggers the dropped event) :
- Pick a treeview item to be dragged
- Drag it slightly over another treeview item
- Put it back at it's original place.
Scenario 2 (not triggering the drop event) :
- Pick an item to be dragged
- drag it directly on another treeview item
- drop it
Scenario 3 (not triggering the drop event):
- Pick a treeview item to be dragged
- drag it to a new location in the treeview (not on another item)
- drop it
Expected behavior
All of these scenarios should trigger the Drop event as all the targets location are valid, but they aren't. In my code, only the children treeview item are bound to the TreeViewItem_Drop method. So only those are expected to call the method (those in the FileTemplate datatemplate).
Screenshots
NuGet package version
WindowsAppSDK 1.7.250513003
Windows version
Windows 11
Additional context
*MainWindow.Xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="TreeView_Drop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TreeView_Drop"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="TreeView-Drop">
<Grid Name="MainGrid">
<Grid.Resources>
<!-- DataTemplate for folders -->
<DataTemplate x:Key="FolderTemplate" x:DataType="local:ExplorerItem">
<TreeViewItem AutomationProperties.Name="{x:Bind Name}"
ItemsSource="{x:Bind Children}" IsExpanded="True">
<StackPanel Orientation="Horizontal">
<Image Width="20" Source="../Assets/SampleMedia/folder.png"/>
<TextBlock Margin="0,0,10,0"/>
<TextBlock Text="{x:Bind Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<!-- DataTemplate for files -->
<DataTemplate x:Key="FileTemplate" x:DataType="local:ExplorerItem">
<TreeViewItem AutomationProperties.Name="{x:Bind Name}" Drop="TreeViewItem_Drop">
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="" />
<TextBlock Margin="0,0,10,0"/>
<TextBlock Text="{x:Bind Name}"/>
</StackPanel>
</TreeViewItem>
</DataTemplate>
<!-- Template selector for ExplorerItem types -->
<local:ExplorerItemTemplateSelector x:Key="ExplorerItemTemplateSelector"
FolderTemplate="{StaticResource FolderTemplate}"
FileTemplate="{StaticResource FileTemplate}" />
</Grid.Resources>
<!-- TreeView bound to DataSource, using the ItemTemplateSelector -->
<TreeView ItemsSource="{x:Bind DataSource}"
ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"
CanDragItems="True"
AllowDrop="True"/>
</Grid>
</Window>
MainWindow.Xaml.cs
using System.Collections.ObjectModel;
using System.Diagnostics;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace TreeView_Drop
{
public sealed partial class MainWindow : Window
{
public ObservableCollection<ExplorerItem> DataSource { get; set; }
public MainWindow()
{
this.InitializeComponent();
DataSource = GetData();
MainGrid.DataContext = this;
}
private ObservableCollection<ExplorerItem> GetData()
{
return new ObservableCollection<ExplorerItem>
{
new ExplorerItem
{
Name = "Documents",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem
{
Name = "ProjectProposal",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem
{
Name = "BudgetReport",
Type = ExplorerItem.ExplorerItemType.File,
},
},
},
new ExplorerItem
{
Name = "Projects",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem
{
Name = "Project Plan",
Type = ExplorerItem.ExplorerItemType.File,
},
},
},
};
}
private void TreeViewItem_Drop(object sender, DragEventArgs e)
{
Debug.WriteLine("Dropped");
}
}
public class ExplorerItem
{
public enum ExplorerItemType
{
Folder,
File,
}
public string Name { get; set; }
public ExplorerItemType Type { get; set; }
public ObservableCollection<ExplorerItem> Children { get; set; } = new ObservableCollection<ExplorerItem>();
}
class ExplorerItemTemplateSelector : DataTemplateSelector
{
// Template to use for folder items in the TreeView.
public DataTemplate FolderTemplate { get; set; }
// Template to use for file items in the TreeView.
public DataTemplate FileTemplate { get; set; }
// Determines which template to use for each item in the TreeView based on its type.
protected override DataTemplate SelectTemplateCore(object item)
{
// Cast the item to the ExplorerItem type.
var explorerItem = (ExplorerItem)item;
// Return the appropriate template: FolderTemplate for folders, FileTemplate for files.
return explorerItem.Type == ExplorerItem.ExplorerItemType.Folder
? FolderTemplate
: FileTemplate;
}
}
}
I was able to repro it in my local. The drag and drop at the same location are triggering the dropped event, moving to other location isn't. This seems like by design, but requires some investigation to confirm.