在WPF應用中使用GongSolutions.WPF.DragDrop實現列表集合控制元件的拖動處理

2023-12-05 12:00:47

WPF應用中,控制元件本身也可以通過實現事件程式碼實現拖動的處理,不過如果我們使用GongSolutions.WPF.DragDrop來處理,事情會變得更加簡單輕鬆,它支援很多控制元件的拖動處理,如ListBox, ListView, TreeView, DataGrid等源自ItemsControl的控制元件,本篇隨筆介紹在工作流模組中拖動TreeView和DataGrid列表實現流程順序的調整處理。

1、使用GongSolutions.WPF.DragDrop

控制元件的GitHub地址:https://github.com/punker76/gong-wpf-dragdrop

使用GongSolutions.WPF.DragDrop比較簡單,和其他類似的做法差不多,首先在Nugget找到並新增對應的控制元件參照,如下所示。

 新增完成相關的參照後,我們在需要使用的XAML頁面中新增對應的名稱空間,如下程式碼上所示。

xmlns:dd="urn:gong-wpf-dragdrop"

主要使用框架依賴屬性:

dd:DragDrop.IsDragSource="True"//是否作為拖拽源
dd:DragDrop.IsDropTarget="False"//是否作為投遞目標
dd:DragDrop.UseDefaultDragAdorner="True"//使用預設的拖拽裝飾器
dd:DragDrop.UseDefaultEffectDataTemplate="True"//使用預設的陰影資料模板
dd:DragDrop.EffectMoveAdornerTemplate//指定移動時的陰影裝飾器模板
dd:DragDrop.DropHandler="{Binding MyDropHandler}"//投下時執行處理器

不過我們一般使用其中的三項就可以了,如下程式碼所示,是基於MVVM的模型繫結

 dd:DragDrop.DropHandler="{Binding ViewModel}"
 dd:DragDrop.IsDragSource="True"
 dd:DragDrop.IsDropTarget="True"

如下列表的介面,就是設定了拖動的事件處理效果

拖動調整後,我們直觀的提示一下介面即可,如下所示。

 前面我們看到程式碼中有  dd:DragDrop.DropHandler="{Binding ViewModel}" ,這個檢視模型裡面就是包含了拖動處理的事件的,我們看看它的定義。

首先檢視模型需要實現介面IDropTarget,以便處理拖動後的順序修改邏輯,它的介面定義如下所示。

我們的檢視模型實現實現IDropTarget介面,包含了兩個Over和Drop的方法的實現,如下程式碼所示。

 主要就是後臺對拖動的響應,以便更新後端的記錄順序,我們通過Seq的順序來調整即可。

 

2、在DataGrid中實現拖動列表

上面介紹的是對於TreeViw控制元件的處理,對於DataGrid的處理方法,也是用類似的方式來實現即可。

其中它的XAML介面程式碼如下所示。

<DataGrid
    x:Name="grid"
    dd:DragDrop.DropHandler="{Binding ViewModel}"
    dd:DragDrop.IsDragSource="True"
    dd:DragDrop.IsDropTarget="True"
    dd:DragDrop.UseDefaultDragAdorner="True"
    hc:DataGridAttach.ShowRowNumber="True"
    AutoGenerateColumns="False"
    HeadersVisibility="All"
    IsReadOnly="True"
    ItemsSource="{Binding ViewModel.Items}"
    MouseDoubleClick="DataGrid_MouseDoubleClick"
    RowHeaderWidth="60"
    SelectionChanged="DataGrid_SelectionChanged"
    SelectionMode="Extended">

同樣我們可以看到的處理方式類似做法,後端頁面程式碼也是實現拖動的順序處理即可,檢視模型實現實現IDropTarget介面,如下是檢視模型程式碼實現。

    #region 控制元件拖放處理
    void IDropTarget.DragOver(IDropInfo dropInfo)
    {
        var sourceItem = dropInfo.Data as FormFlowInfo;
        var targetItem = dropInfo.TargetItem as FormFlowInfo;

        if (sourceItem != null && targetItem != null)// && targetItem.CanAcceptChildren)
        {
            dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
            dropInfo.Effects = DragDropEffects.Copy;
        }
    }

    async void IDropTarget.Drop(IDropInfo dropInfo)
    {
        var sourceItem = (FormFlowInfo)dropInfo.Data;
        var targetItem = (FormFlowInfo)dropInfo.TargetItem;
        string dragMenuId = sourceItem.Id;
        string dropMenuId = targetItem.Id;
        try
        {
            if (!dragMenuId.IsNullOrEmpty() && !dropMenuId.IsNullOrEmpty())
            {
                await BLLFactory<IFormFlowService>.Instance.UpdateTwoSeq(dragMenuId, dropMenuId);
                await GetData();
                GrowlUtil.ShowInfo("已調整了步驟順序");
            }
        }
        catch (Exception ex)
        {
            LogTextHelper.Error(ex);
            GrowlUtil.ShowError(ex.Message);
        }
    }
    #endregion

 

以上就是在WPF應用中使用GongSolutions.WPF.DragDrop實現列表集合控制元件的拖動處理,它在其他各型別列表集合控制元件中使用都是類似的方式,因此比較好用,而且實現的效果也比較不錯,強烈推薦。