XamDataGrid レコードのドラッグアンドドロップを実装してみましょう。XamDataGrid 単体ではドラッグアンドドロップの機能ありませんが、 Infragistics WPF に含まれる Infragistics Drag and Drop Framework を組み合わせることで実現することができます。
XamDataGrid のレコードは DataRecordPresenter として描画されており、ドラッグアンドドロップ機能を DataRecordPresenter に割り当てていきます。
Snoop を使って XamDataGrid を覗いてみます。DataRecordPresenter はここです。
実装の手順
1. DataRecordPresenter のテンプレートを取り込む
DataRecordPresenter のテンプレートをアプリケーション内に取り込み、ドラッグアンドドロップ機能を追加して上書きします。テンプレートは下記ファイルパスの DataPresenterGeneric_Express.xaml にあります。
C:\Program Files (x86)\Infragistics\2019.1\WPF\DefaultStyles\DataPresenter
→ DataPresenterGeneric_Express.xaml
2. 取り込んだテンプレートのカスタマイズ
DataRecordPresenter の ContentPresenter(x:Name=”PART_RecordContentSite”)に DragDropManager を設定します。DragSource の IsDraggable を True にすることでレコードのドラッグができるようになります。また、DropTarget の IsDropTarget を True にすることでレコードのドロップができるようになります。
続いて、DragSource の Drop イベントをハンドルしてドラッグされたレコードとドロップされた位置を判定してレコード位置の制御を行います。DataRecordPresenter のテンプレートには DragDropBehavior(後述) を設定します。
ここまでの実装内容は下記コードスニペットの 13 – 24 行目と対応します。
<Style TargetType="{x:Type igDP:DataRecordPresenter}"> ... <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type igDP:DataRecordPresenter}"> <igWindows:CardPanel x:Name="baseGrid" RenderTransform="{TemplateBinding FixedNearElementTransform}" Background="{TemplateBinding Background}"> <Border x:Name="addRowFooter" ... /> <Grid Margin="0" RenderTransform="{TemplateBinding ScrollableElementTransform}"> ... <ContentPresenter x:Name="PART_RecordContentSite" ...> <!--ドラッグアンドドロップの設定--> <ig:DragDropManager.DragSource> <ig:DragSource IsDraggable="True"> <i:Interaction.Behaviors> <!--ビヘイビアの設定--> <behaviors:DragDropBehavior/> </i:Interaction.Behaviors> </ig:DragSource> </ig:DragDropManager.DragSource> <ig:DragDropManager.DropTarget> <ig:DropTarget IsDropTarget="True"/> </ig:DragDropManager.DropTarget> <!--ドラッグアンドドロップの設定--> </ContentPresenter> ... </Grid> </igWindows:CardPanel> ... </ControlTemplate> </Setter.Value> </Setter> ... </Style>
3. DragDropBehavior の実装
次に、DragDropBehavior に DragSource のレコードがドロップされたタイミングで発生する Drop イベントを実装していきます。
public class DragDropBehavior : Behavior<DragSource> { protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.Drop += AssociatedObject_Drop; } private void AssociatedObject_Drop(object sender, DropEventArgs e) { System.Diagnostics.Debug.WriteLine("Drop"); DragSource dragSource = sender as DragSource; FrameworkElement fe = dragSource.AssociatedObject as FrameworkElement; Record record = fe.DataContext as Record; // XamDataGrid の取得 XamDataGrid presenter = record.DataPresenter as XamDataGrid; // ドラッグレコードの取得 ContentPresenter source = e.DragSource as ContentPresenter; DataRecord sourceRecord = source.DataContext as DataRecord; int sourceIndex = sourceRecord.Index; // ドロップレコードの取得 ContentPresenter target = e.DropTarget as ContentPresenter; DataRecord targetRecord = target.DataContext as DataRecord; int targetIndex = targetRecord.Index; var dc = presenter.DataContext; MainViewModel vm = dc as MainViewModel; // ドラッグレコードの位置変更 vm.Tasks.Move(sourceIndex, targetIndex); } protected override void OnDetaching() { this.AssociatedObject.Drop -= AssociatedObject_Drop; base.OnDetaching(); } }
実行結果
レコードのドラッグアンドドロップができるようになりました。
サンプル
オンラインリソース
DataRecordPresenter クラス https://jp.infragistics.com/help/wpf/infragisticswpf.datapresenter~infragistics.windows.datapresenter.datarecordpresenter
Infragistics Drag and Drop Framework
https://jp.infragistics.com/help/wpf/drag-and-drop-framework