ドラッグアンドドロップでデータを並べ替えます。
カテゴリからカテゴリにドラッグアンドドロップされた場合はドラッグ元のカテゴリをドロップされた位置のひとつ上に移動します。下のほうにあるカテゴリを一番上のカテゴリの上にドロップしたら一番上に表示されるカテゴリになるのです。
タスクからカテゴリにドラッグアンドドロップされた場合はそのタスクをカテゴリの一番最後に移動させます。
タスクからタスクにドラッグアンドドロップされた場合はドラッグ元のタスクをドロップ先のタスクのひとつ上に移動します。
CategoryUserControlはTaskUserControlのリストをフィールド変数として持っています。またTaskUserControlは自分が属するカテゴリのCategoryUserControlとそのカテゴリがもつタスクのリストをフィールド変数として持っています。タスクは自分が属するカテゴリが変わると自分が属するカテゴリのタスクのリストも変更しなければなりません。
CategoryUserControlに以下を追加します。
まずコンストラクタにドラッグアンドドロップを許可するためのコードを追加します。そしてマウスがクリックされたらDoDragDropメソッドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public partial class CategoryUserControl : UserControl { public CategoryUserControl(List<CategoryUserControl> categoryUserControls) { InitializeComponent(); InitContextMenu(); BackColor = Color.White; BorderStyle = BorderStyle.FixedSingle; CategoryUserControls = categoryUserControls; // ドラッグアンドドロップを許可する AllowDrop = true; // ラベルがクリックされたときもドラッグの開始処理をおこなう label1.MouseDown += Label1_MouseDown; } protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) DoDragDrop(this, DragDropEffects.Move); base.OnMouseDown(e); } private void Label1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) DoDragDrop(this, DragDropEffects.Move); } } |
CategoryUserControlまたはTaskUserControlがマウスドラッグされているときはマウスカーソルの形状を変えて移動できるようにします。そしてドロップされたらMoveTaskUserControlメソッドまたはMoveCategoryUserControlメソッドを呼び出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class CategoryUserControl : UserControl { protected override void OnDragOver(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(typeof(CategoryUserControl))) drgevent.Effect = DragDropEffects.Move; else if (drgevent.Data.GetDataPresent(typeof(TaskUserControl))) drgevent.Effect = DragDropEffects.Move; else drgevent.Effect = DragDropEffects.None; base.OnDragOver(drgevent); } protected override void OnDragDrop(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(typeof(CategoryUserControl))) { CategoryUserControl categoryUserControl = (CategoryUserControl)drgevent.Data.GetData(typeof(CategoryUserControl)); if (this != categoryUserControl) MoveCategoryUserControl(categoryUserControl); } else if (drgevent.Data.GetDataPresent(typeof(TaskUserControl))) { TaskUserControl taskUserControl = (TaskUserControl)drgevent.Data.GetData(typeof(TaskUserControl)); MoveTaskUserControl(taskUserControl); } base.OnDragDrop(drgevent); } } |
カテゴリの上にカテゴリがドロップされたらカテゴリの順番を変更します。そしてCategoryUserControls内に格納されているCategoryUserControlの順番を変更したらForm1クラスのShowChartメソッドを呼び出します。クラスの外から呼び出せるようにShowChartメソッドはpublicに変更しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class CategoryUserControl : UserControl { void MoveCategoryUserControl(CategoryUserControl moveFrom) { this.CategoryUserControls.Remove(moveFrom); int toIndex = this.CategoryUserControls.IndexOf(this); this.CategoryUserControls.Insert(toIndex, moveFrom); Form1 form1 = (Form1)FindForm(); form1.ShowChart(); } } |
カテゴリの上にタスクがドロップされたらカテゴリの最後にそのタスクを移動します。このときそのタスクが所属するカテゴリも変更しなければなりません。TaskUserControl.CategoryUserControlはプロパティで属するカテゴリを変更することでその他の変更も同時におこなえるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class CategoryUserControl : UserControl { void MoveTaskUserControl(TaskUserControl moveFrom) { CategoryUserControl categoryUserControl = moveFrom.CategoryUserControl; categoryUserControl.TaskUserControls.Remove(moveFrom); this.TaskUserControls.Add(moveFrom); // タスクが異なるカテゴリ間で移動する場合はいろいろ面倒な処理をプロパティでおこなう if (categoryUserControl != this) moveFrom.CategoryUserControl = this; Form1 form1 = (Form1)FindForm(); form1.ShowChart(); } } |
次にTaskUserControlクラスに変更を加えます。やはりここでもドラッグアンドドロップの処理を考えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class TaskUserControl : UserControl { public TaskUserControl(CategoryUserControl categoryUserControl, List<TaskUserControl> taskUserControls) { InitializeComponent(); InitContextMenu(); BorderStyle = BorderStyle.None; CategoryUserControl = categoryUserControl; TaskUserControls = taskUserControls; AllowDrop = true; // ラベルがクリックされたときもドラッグの開始処理をおこなう label1.MouseDown += Label1_MouseDown; label2.MouseDown += Label1_MouseDown; } } |
先述したCategoryUserControlプロパティの処理を示します。CategoryUserControlが変更されたらCategoryUserControl.TaskUserControlsも変更しなければなりません。また親のコントロールが変わってしまう場合も考えられます。その場合の処理もおこなっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class TaskUserControl : UserControl { CategoryUserControl _categoryUserControl; public CategoryUserControl CategoryUserControl { set { CategoryUserControl oldControl = _categoryUserControl; _categoryUserControl = value; TaskUserControls = value.TaskUserControls; // 親コントロールが変わってしまう場合もありうる if (oldControl != _categoryUserControl) { if (oldControl != null) oldControl.Controls.Remove(this); if (_categoryUserControl != null) _categoryUserControl.Controls.Add(this); } } get { return _categoryUserControl; } } } |
ドラッグアンドドロップに関する処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public partial class TaskUserControl : UserControl { private void Label1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) DoDragDrop(this, DragDropEffects.Move); } protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) DoDragDrop(this, DragDropEffects.Move); base.OnMouseDown(e); } protected override void OnDragOver(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(typeof(TaskUserControl))) drgevent.Effect = DragDropEffects.Move; else drgevent.Effect = DragDropEffects.None; base.OnDragOver(drgevent); } protected override void OnDragDrop(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(typeof(TaskUserControl))) { TaskUserControl taskUserControl = (TaskUserControl)drgevent.Data.GetData(typeof(TaskUserControl)); MoveTaskUserControl(taskUserControl); } base.OnDragDrop(drgevent); } } |
タスクを同じカテゴリ内または異なるカテゴリへ移動させる処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class TaskUserControl : UserControl { void MoveTaskUserControl(TaskUserControl moveFrom) { moveFrom.TaskUserControls.Remove(moveFrom); int index = this.TaskUserControls.IndexOf(this); this.TaskUserControls.Insert(index, moveFrom); if (moveFrom.CategoryUserControl != this.CategoryUserControl) moveFrom.CategoryUserControl = this.CategoryUserControl; Form1 form1 = (Form1)FindForm(); form1.ShowChart(); } } |
それからタスクを削除する処理も追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public partial class TaskUserControl : UserControl { ContextMenuStrip ContextMenuStrip1 = new ContextMenuStrip(); ToolStripMenuItem SetTaskDateMenuItem = new ToolStripMenuItem(); ToolStripMenuItem AddTaskPrevMenuItem = new ToolStripMenuItem(); ToolStripMenuItem AddTaskNextMenuItem = new ToolStripMenuItem(); ToolStripMenuItem RemoveTaskMenuItem = new ToolStripMenuItem(); void InitContextMenu() { this.ContextMenuStrip = this.ContextMenuStrip1; // 既存のメニュー SetTaskDateMenuItem.Text = "日時設定"; SetTaskDateMenuItem.Click += SetTaskDateMenuItem_Click; AddTaskPrevMenuItem.Text = "この上にタスク追加"; AddTaskPrevMenuItem.Click += AddTaskPrevMenuItem_Click; ; AddTaskNextMenuItem.Text = "この下にタスク追加"; AddTaskNextMenuItem.Click += AddTaskNextMenuItem_Click; ; // 新たに追加 RemoveTaskMenuItem.Text = "タスクを削除"; RemoveTaskMenuItem.Click += RemoveTaskMenuItem_Click; this.ContextMenuStrip.Items.AddRange(new ToolStripItem[] { SetTaskDateMenuItem, new ToolStripSeparator(), AddTaskPrevMenuItem, AddTaskNextMenuItem, new ToolStripSeparator(), RemoveTaskMenuItem, }); } private void RemoveTaskMenuItem_Click(object sender, EventArgs e) { Form1 form1 = (Form1)FindForm(); TaskUserControls.Remove(this); CategoryUserControl.Controls.Remove(this); form1.ShowChart(); } } |
カテゴリの削除はカテゴリ内のタスクが0になったら自動的に消えます。