WinUI3/UWP中是否有类似ListView InsertionMark的功能?
WinUI3/UWP中实现类似ListView InsertionMark的拖放插入功能
WinUI3/UWP没有内置与WinForms的ListView.InsertionMark完全匹配的功能,但可以通过拖放事件结合自定义逻辑,实现获取拖放插入位置索引并显示插入标记的效果。
实现步骤
1. 配置ListView的拖放属性
给目标ListView开启拖放支持:
<ListView x:Name="TargetListView" AllowDrop="True" DragEnter="TargetListView_DragEnter" DragOver="TargetListView_DragOver" Drop="TargetListView_Drop"> <!-- 你的ItemTemplate和数据源配置 --> </ListView>
2. 计算拖放插入位置索引
在DragOver事件中,通过鼠标位置判断插入的目标索引:
private int _insertionIndex = -1; private void TargetListView_DragOver(object sender, DragEventArgs e) { var listView = sender as ListView; if (listView == null) return; // 获取鼠标在ListView内的位置 Point position = e.GetPosition(listView); // 找到鼠标下方的列表项容器 var itemContainer = listView.ContainerFromPosition(position) as ListViewItem; if (itemContainer != null) { // 获取该项对应的数据源索引 int itemIndex = listView.IndexFromContainer(itemContainer); // 获取容器的边界 GeneralTransform transform = itemContainer.TransformToVisual(listView); Rect itemRect = transform.TransformBounds(new Rect(0, 0, itemContainer.ActualWidth, itemContainer.ActualHeight)); // 判断鼠标位置是在项的上半部分还是下半部分,决定插入位置 if (position.Y < itemRect.Top + itemRect.Height / 2) { _insertionIndex = itemIndex; } else { _insertionIndex = itemIndex + 1; } } else { // 鼠标不在任何项上,插入到列表末尾 _insertionIndex = listView.Items.Count; } // 更新插入标记的显示位置 UpdateInsertionMarkerPosition(_insertionIndex); }
3. 自定义插入标记UI
在ListView的布局中添加用于显示插入线的元素(如Rectangle),通过UpdateInsertionMarkerPosition方法调整其位置:
private void UpdateInsertionMarkerPosition(int index) { if (index < 0 || index > TargetListView.Items.Count) { InsertionLine.Visibility = Visibility.Collapsed; return; } InsertionLine.Visibility = Visibility.Visible; ListViewItem targetItem = null; if (index < TargetListView.Items.Count) { targetItem = TargetListView.ContainerFromIndex(index) as ListViewItem; } else { // 插入到末尾时,基于最后一项的位置计算 targetItem = TargetListView.ContainerFromIndex(TargetListView.Items.Count - 1) as ListViewItem; } if (targetItem != null) { GeneralTransform transform = targetItem.TransformToVisual(TargetListView); Rect itemRect = transform.TransformBounds(new Rect(0, 0, targetItem.ActualWidth, targetItem.ActualHeight)); // 调整插入线的位置(示例为垂直插入线,可根据布局修改为水平) InsertionLine.Margin = new Thickness(index == 0 ? 0 : itemRect.Left, itemRect.Top, 0, itemRect.Height); InsertionLine.Width = 2; InsertionLine.Fill = new SolidColorBrush(Colors.Blue); } }
4. 完成拖放插入操作
在Drop事件中,使用计算好的_insertionIndex完成数据插入:
private async void TargetListView_Drop(object sender, DragEventArgs e) { if (e.DataView.Contains(StandardDataFormats.Text)) // 根据实际拖放的数据类型调整 { string draggedItem = await e.DataView.GetTextAsync(); var itemsSource = TargetListView.ItemsSource as ObservableCollection<string>; if (itemsSource != null && _insertionIndex >= 0 && _insertionIndex <= itemsSource.Count) { itemsSource.Insert(_insertionIndex, draggedItem); } } // 隐藏插入标记 InsertionLine.Visibility = Visibility.Collapsed; }
内容的提问来源于stack exchange,提问作者yonutix
相关产品推荐
相关产品推荐

