行のドラッグ&ドロップが可能な
DataGridView。
ちょっとバグがあるけれど一応動作する。
DataSourceには対応できない。
ViewのCellに直接データを突っ込んで使用可能。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace MyReName.ctrl
{
class DragAbleDataGridView : DataGridView
{
private int mintCurrentRowIndex = -1;
private int mintNextRowIndex = -1;
private bool mboolMoveToEndRowFlg = false;
private int[] dragRowIndex;
private bool Flg = true;
private Label lblBar = new Label();
public Color DropDawnBarColor
{
get
{
return lblBar.BackColor;
}
set
{
lblBar.BackColor = value;
}
}
/// <summary>
/// コンストラクタ
/// </summary>
public DragAbleDataGridView()
{
this.InitCtrl();
}
/// <summary>
/// コンポーネントの初期化処理
/// </summary>
private void InitCtrl()
{
// DataGridViewの初期設定
this.AutoGenerateColumns = false;
this.BackgroundColor = Color.White;
this.CellBorderStyle = DataGridViewCellBorderStyle.None;
this.RowHeadersVisible = false;
this.AllowUserToResizeRows = false;
this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.AllowUserToAddRows = false;
this.AllowUserToDeleteRows = false;
this.AllowDrop = true;
this.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.False;
// イベントを追加
this.DragDrop += new DragEventHandler(DragAbleDataGridView_DragDrop);
this.DragEnter += new DragEventHandler(DragAbleDataGridView_DragEnter);
this.MouseDown += new MouseEventHandler(DragAbleDataGridView_MouseDown);
this.MouseMove += new MouseEventHandler(DragAbleDataGridView_MouseMove);
this.DragOver += new DragEventHandler(DragAbleDataGridView_DragOver);
this.DragLeave += new EventHandler(DragAbleDataGridView_DragLeave);
this.QueryContinueDrag += new QueryContinueDragEventHandler(DragAbleDataGridView_QueryContinueDrag);
this.RowValidating += new DataGridViewCellCancelEventHandler(DragAbleDataGridView_RowValidating);
// ドラッグ中に表示するバーを追加
this.Controls.Add(lblBar);
lblBar.Visible = false;
lblBar.BackColor = Color.Red;
lblBar.Size = new Size(this.Width, 2);
}
/// <summary>
/// MouseDownイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_MouseDown(object sender, MouseEventArgs e)
{
mintCurrentRowIndex = -1;
// 左クリック以外はリターン
if ((e.Button & MouseButtons.Left) != MouseButtons.Left)
{
return;
}
// セルクリック以外はリターン
DataGridView.HitTestInfo hitInfo = this.HitTest(e.X, e.Y);
if (hitInfo.Type != DataGridViewHitTestType.Cell)
{
return;
}
mintCurrentRowIndex = hitInfo.RowIndex;
// 既に選択されているセルを選択している場合(ここの動作がうまくいかない…)
if (this.Rows[mintCurrentRowIndex].Selected && ModifierKeys == Keys.None)
{
ReSetDragRowsIndexies();
Flg = true;
}
// 未選択のセルを選択している場合
else
{
dragRowIndex = null;
Flg = false;
}
}
/// <summary>
/// 行の検証時の処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
if (Flg)
{
e.Cancel = true;
Flg = false;
}
}
/// <summary>
/// MouseMoveイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_MouseMove(object sender, MouseEventArgs e)
{
// 左ボタン以外はリターン
if ((e.Button & MouseButtons.Left) != MouseButtons.Left)
{
return;
}
// Row未選択はリターン
if (mintCurrentRowIndex == -1)
{
return;
}
// ドラッグ開始
this.DoDragDrop(mintCurrentRowIndex, DragDropEffects.Move);
}
/// <summary>
/// ドラッグ対象行のインデックスを記憶
/// </summary>
private void ReSetDragRowsIndexies()
{
dragRowIndex = new int[this.SelectedRows.Count];
for (int i = 0; i < this.SelectedRows.Count; i++)
{
dragRowIndex[i] = this.SelectedRows[i].Index;
}
}
/// <summary>
/// DragOverイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_DragOver(object sender, DragEventArgs e)
{
if (mintCurrentRowIndex == -1)
{
return;
}
e.Effect = DragDropEffects.Move;
if (dragRowIndex == null)
{
ReSetDragRowsIndexies();
}
// ドラッグ位置を取得
Point clientPoint = this.PointToClient(new Point(e.X, e.Y));
DataGridView.HitTestInfo hitInfo = this.HitTest(clientPoint.X, clientPoint.Y);
mboolMoveToEndRowFlg = false;
if (hitInfo.RowIndex == -1)
{
if (mintCurrentRowIndex == this.Rows.Count - 1)
{
mboolMoveToEndRowFlg = true;
}
}
else
{
mintNextRowIndex = hitInfo.RowIndex;
}
if (mboolMoveToEndRowFlg)
{
Rectangle rec = this.GetRowDisplayRectangle(mintNextRowIndex, true);
lblBar.Location = new Point(0, rec.Bottom);
lblBar.Visible = true;
}
else if (mintCurrentRowIndex == mintNextRowIndex && mintCurrentRowIndex == this.Rows.Count - 1)
{
Rectangle rec = this.GetRowDisplayRectangle(mintNextRowIndex, true);
lblBar.Location = new Point(0, rec.Top);
lblBar.Visible = true;
}
else if (mintCurrentRowIndex != mintNextRowIndex)
{
Rectangle rec = this.GetRowDisplayRectangle(mintNextRowIndex, true);
lblBar.Location = new Point(0, rec.Top);
mintCurrentRowIndex = mintNextRowIndex;
lblBar.Visible = true;
}
}
/// <summary>
/// DataGridViewの外へドラッグしたらドラッグをキャンセル
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_DragLeave(object sender, EventArgs e)
{
if (!lblBar.Visible)
{
return;
}
ExitDrag();
}
/// <summary>
/// DragEnter
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_DragEnter(object sender, DragEventArgs e)
{
if (lblBar.Visible)
{
return;
}
e.Effect = DragDropEffects.All;
}
/// <summary>
/// ドラッグ継続中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DragAbleDataGridView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
// 右クリック押下時
if ((e.KeyState & 2) == 2)
{
// ドラッグをキャンセル
e.Action = DragAction.Cancel;
ExitDrag();
}
}
/// <summary>
/// 行データの移動
/// </summary>
/// <param name="FromIndex"></param>
/// <param name="ToIndex"></param>
/// <returns>実際の移動先インデックス</returns>
private int MoveTo(int FromIndex, int ToIndex)
{
DataGridViewRow row;
int MoveToIndex = ToIndex;
if (FromIndex != ToIndex)
{
row = (DataGridViewRow)this.Rows[FromIndex].Clone();
for (int i = 0; i < this.Columns.Count; i++)
{
row.Cells[i].Value = this.Rows[FromIndex].Cells[i].Value;
}
if (FromIndex > ToIndex)
{
this.Rows.RemoveAt(FromIndex);
this.Rows.Insert(ToIndex, row);
}
else if (FromIndex < ToIndex)
{
if (mboolMoveToEndRowFlg)
{
this.Rows.RemoveAt(FromIndex);
this.Rows.Insert(ToIndex, row);
}
else
{
this.Rows.RemoveAt(FromIndex);
this.Rows.Insert(ToIndex - 1, row);
MoveToIndex = ToIndex - 1;
}
}
}
return MoveToIndex;
}
private void DragAbleDataGridView_DragDrop(object sender, DragEventArgs e)
{
// 行のDragDropの場合
if (lblBar.Visible)
{
Flg = false;
Array.Sort(dragRowIndex);
int ShiftFront = 0;
int ShiftBack = 0;
int MoveFromIndex = 0;
int MoveToIndex = 0;
int MinRowIndex = mintCurrentRowIndex;
int MaxRowIndex = mintCurrentRowIndex;
int SelectionStaIndex = 0;
// 行を移動
for (int i = 0; i < dragRowIndex.GetLength(0); i++)
{
MoveFromIndex = dragRowIndex[i];
MoveToIndex = mintCurrentRowIndex;
if (MinRowIndex > MoveFromIndex)
{
MinRowIndex = MoveFromIndex;
}
else if (MinRowIndex > MoveToIndex)
{
MinRowIndex = MoveToIndex;
}
if (MaxRowIndex < MoveFromIndex)
{
MaxRowIndex = MoveFromIndex;
}
else if (MaxRowIndex < MoveToIndex)
{
MaxRowIndex = MoveToIndex;
}
if (i > 0)
{
if (MoveFromIndex < MoveToIndex)
{
ShiftFront--;
MoveFromIndex += ShiftFront;
}
else if (MoveFromIndex > MoveToIndex)
{
if (dragRowIndex[i - 1] >= MoveToIndex)
{
ShiftBack++;
MoveToIndex += ShiftBack;
}
}
}
if (i == 0)
{
SelectionStaIndex = MoveTo(MoveFromIndex, MoveToIndex);
}
else
{
MoveTo(MoveFromIndex, MoveToIndex);
}
}
// 移動後の行を選択
this.CurrentCell = this.Rows[SelectionStaIndex + ShiftFront].Cells[0];
this.ClearSelection();
for (int i = 0; i < dragRowIndex.GetLength(0); i++)
{
this.Rows[SelectionStaIndex + ShiftFront + i].Selected = true;
}
ExitDrag();
}
// DataGridView外からのDragDropの場合
else
{
//DragDropされたファイルパスをセルに追加
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
foreach (string filePath in (string[])e.Data.GetData(DataFormats.FileDrop))
{
if (this.Columns.Count > 0)
{
this.Rows.Add();
this.Rows[this.Rows.Count - 1].Cells[0].Value = filePath;
}
}
}
}
}
/// <summary>
/// ドラッグの終了処理
/// </summary>
private void ExitDrag()
{
mintCurrentRowIndex = -1;
//_DragMode = eDraggingMode.None;
lblBar.Visible = false;
this.DoDragDrop(mintCurrentRowIndex, DragDropEffects.None);
}
}
}
最終更新:2012年01月11日 00:26