You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3 ListView获取项拖放后的位置(重排场景)

WinUI3 ListView拖放重排后获取项的新索引

默认的DragItemsCompletedEventArgs和DragEventArgs确实没有直接提供拖放后的索引信息,你可以通过以下两种方法解决:

方法一:通过DragItemsStarting + DragItemsCompleted事件结合

思路

拖动开始时记录被拖动的项,拖放完成后遍历ListView的Items集合,找到该项的新位置。

步骤1:定义成员变量存储被拖动项

在TableContentPage类中添加成员变量:

private:
    winrt::Windows::Foundation::IInspectable m_draggedItem;

步骤2:在DragItemsStarting事件中记录被拖动项

实现OnStagedDragItemsStarting方法:

void TableContentPage::OnStagedDragItemsStarting(
    [[maybe_unused]] ::winrt::Windows::Foundation::IInspectable const& sender,
    ::winrt::Microsoft::UI::Xaml::Controls::DragItemsStartingEventArgs const& args)
{
    // 记录第一个被拖动的项(支持多选的话可遍历args.Items()记录所有项)
    if (args.Items().Size() > 0)
    {
        m_draggedItem = args.Items().GetAt(0);
    }
}

步骤3:在DragItemsCompleted事件中获取新索引

更新OnStagedDragItemsCompleted方法:

void TableContentPage::OnStagedDragItemsCompleted(
    [[maybe_unused]] ::winrt::Windows::Foundation::IInspectable const&,
    ::winrt::Microsoft::UI::Xaml::Controls::DragItemsCompletedEventArgs const& args)
{
    // 仅当拖放成功时处理
    if (m_draggedItem != nullptr && args.DropResult() == winrt::Microsoft::UI::Xaml::DragDrop::DragDropResult::Completed)
    {
        auto items = ListViewName.Items();
        for (uint32_t i = 0; i < items.Size(); ++i)
        {
            if (items.GetAt(i) == m_draggedItem)
            {
                uint32_t newIndex = i;
                // 这里使用新索引做后续操作
                break;
            }
        }
        // 重置变量
        m_draggedItem = nullptr;
    }
}

方法二:通过ObservableCollection的CollectionChanged事件(MVVM场景)

如果你的ListView绑定了ObservableCollection,可以直接监听集合的变化——拖放重排会触发Move类型的集合变更事件,直接获取新旧索引。

示例代码

假设你的ViewModel中有如下集合:

winrt::Microsoft::UI::Xaml::Data::ObservableCollection<YourItemType> m_items;

订阅CollectionChanged事件:

// 在ViewModel初始化或绑定集合时添加订阅
m_items.CollectionChanged([this](const auto& sender, const winrt::Microsoft::UI::Xaml::Data::NotifyCollectionChangedEventArgs& args)
{
    if (args.Action() == winrt::Microsoft::UI::Xaml::Data::NotifyCollectionChangedAction::Move)
    {
        uint32_t oldIndex = args.OldStartingIndex();
        uint32_t newIndex = args.NewStartingIndex();
        // 这里直接获取到拖放前后的索引
    }
});

注意事项

  • 若支持多项目拖放,方法一中需要记录所有被拖动的项,遍历Items集合时逐个匹配索引。
  • 方法二更适合MVVM架构,无需依赖UI控件的事件,直接从数据源层面监听变化。

内容的提问来源于stack exchange,提问作者yonutix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:47:27