予定といってもカテゴリのようなものがあります。カテゴリを作成して表示順も変更できるようにしました。
最初に設定したカテゴリもファイルに保存できるようにしたいので、ファイルに保存する部分を変更します。Docというクラスを作成して、このなかにDataのリストとカテゴリの文字列のリストを保存できるようにします。
1 2 3 4 5 |
public class Doc { public List<Data> datas = null; public List<string> Categories = null; } |
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 |
public partial class Form1 : Form { private void buttonSaveFile_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "データファイル|*.dat"; dialog.Title = "データを保存"; if(dialog.ShowDialog() != DialogResult.OK) return; Doc doc = new Doc(); doc.datas = datas; doc.Categories = Categories; XmlSerializer xml = new XmlSerializer(typeof(Doc)); using(StreamWriter sw = new StreamWriter(dialog.FileName)) { xml.Serialize(sw, doc); } } private void buttonLoadFile_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "データファイル|*.dat"; dialog.Title = "ファイルの読み出し"; if(dialog.ShowDialog() != DialogResult.OK) return; XmlSerializer xml = new XmlSerializer(typeof(Doc)); using(StreamReader sr = new StreamReader(dialog.FileName)) { Doc doc = (Doc)xml.Deserialize(sr); datas = doc.datas; Categories = doc.Categories; UpdateListViewItems(); } } } |
つぎに、カテゴリを設定するフォームを表示させます。
リストボックスに設定したカテゴリ名が並びます。ボタンをおすと新規カテゴリ、既存のカテゴリ名の変更、削除ができます。ドラッグ&ドロップをすると表示の順番を変更することができます。
カテゴリは文字列だけでなく表示の順番も設定できるようにします。そこでCategoryItemクラスを作成しました。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { // カテゴリを設定するフォームを表示させるためのハンドラ private void buttonEditCategory_Click(object sender, EventArgs e) { // 詳細はあとで考える EditCategoryForm f = new EditCategoryForm(); if(f.ShowDialog() != DialogResult.OK) return; } } |
1 2 3 4 5 6 7 8 9 10 11 |
public class CategoryItem { public CategoryItem(string categoryName, int categoryID) { CategoryName = categoryName; CategoryID = categoryID; } public string CategoryName = ""; public int CategoryID = 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class EditCategoryForm : Form { public EditCategoryForm() { InitializeComponent(); buttonEditFinished.DialogResult = DialogResult.OK; // ドラッグ&ドロップで操作できるようにする listBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.listBox1_DragDrop); listBox1.DragOver += new System.Windows.Forms.DragEventHandler(this.listBox1_DragOver); listBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.listBox1_MouseDown); } public List<CategoryItem> Categories = null; public int nextNewID = 0; public List<int> deleteIDs = new List<int>(); } |
フォームがロードされたら、コンボボックスに既存のカテゴリ名を挿入します。IDは表示順を管理する役目も持たせています。[追加]ボタンを押すと新しいカテゴリ名が追加されるとともにIDも付与されます。またカテゴリが削除された場合、メインのフォーム側でもどれが削除されたかわかるように、削除されたIDもリストに格納しています。
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 47 48 49 |
public partial class EditCategoryForm : Form { private void EditCategoryForm_Load(object sender, EventArgs e) { foreach(CategoryItem category in Categories) { listBox1.Items.Add(category.CategoryName); } nextNewID = Categories.Count; } private void buttonAdd_Click(object sender, EventArgs e) { string str = textBox1.Text; if(str == "") return; listBox1.Items.Add(str); Categories.Add(new CategoryItem(str, nextNewID)); nextNewID++; textBox1.Text = ""; } private void buttonDelete_Click(object sender, EventArgs e) { int delIndex = listBox1.SelectedIndex; if(delIndex == -1) return; deleteIDs.Add(Categories[delIndex].CategoryID); Categories.RemoveAt(delIndex); listBox1.Items.Clear(); foreach(CategoryItem category in Categories) { listBox1.Items.Add(category.CategoryName); } } private void buttonEdit_Click(object sender, EventArgs e) { int editIndex = listBox1.SelectedIndex; if(editIndex == -1) return; Categories[editIndex].CategoryName = textBox2.Text; listBox1.Items[editIndex] = textBox2.Text; } } |
項目がドラッグ&ドロップされたら表示順を変更します。List
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 47 48 49 50 |
public partial class EditCategoryForm : Form { private void listBox1_MouseDown(object sender, MouseEventArgs e) { int i = listBox1.SelectedIndex; if(i == -1) return; listBox1.DoDragDrop(i, DragDropEffects.Move); } private void listBox1_DragOver(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { e.Effect = DragDropEffects.Move; Point pt = listBox1.PointToClient(new Point(e.X, e.Y)); int index = listBox1.IndexFromPoint(pt); if(index != -1) listBox1.SelectedIndex = index; } } private void listBox1_DragDrop(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { Point pt = listBox1.PointToClient(new Point(e.X, e.Y)); int index = listBox1.IndexFromPoint(pt); if(index != -1) { int sourceIndex = (int)e.Data.GetData(typeof(int)); if(sourceIndex == index) return; var sourceItem = Categories[sourceIndex]; var targetItem = Categories[index]; Categories.RemoveAt(sourceIndex); int target = Categories.IndexOf(targetItem); Categories.Insert(target, sourceItem); listBox1.Items.Clear(); foreach(CategoryItem category in Categories) { listBox1.Items.Add(category.CategoryName); } } } } } |
それではメインフォームの[カテゴリ編集]ボタンがクリックされたときの処理を示します。
最初にEditCategoryFormクラスからフォームを生成します。そしてコンボボックスに既存のカテゴリ名を挿入して、フォームが表示されたときにデータが属するカテゴリが選択されるように変数に値もセットします。
カテゴリ設定フォームで[編集完了]がクリックされたら、削除されたカテゴリとカテゴリの順番の変更を調べます。これはDataクラスの値を書き換える必要があるため、情報を集めておく必要があります。(コメントが書かれている部分)
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 47 48 49 50 51 52 53 54 55 56 57 58 |
public partial class Form1 : Form { List<string> Categories = new List<string>(); private void buttonEditCategory_Click(object sender, EventArgs e) { EditCategoryForm f = new EditCategoryForm(); int i = 0; List<CategoryItem> items = new List<CategoryItem>(); foreach(string str in Categories) { CategoryItem item = new CategoryItem(str, i); items.Add(item); i++; } f.Categories = items; if(f.ShowDialog() != DialogResult.OK) return; List<Data2> data2s = new List<Data2>(); // 削除されてしまったカテゴリに属するデータを集める foreach(int id in f.deleteIDs) { Data2 data2 = new Data2(); data2.datas = datas.Where(x => x.Category == id).ToList(); data2.newID = -1; data2s.Add(data2); } i = 0; Categories.Clear(); // カテゴリIDが変更されたカテゴリに属するデータを集める foreach(CategoryItem item in f.Categories) { Categories.Add(item.CategoryName); int newID = i; int oldID = item.CategoryID; i++; Data2 data2 = new Data2(); data2.datas = datas.Where(x => x.Category == oldID).ToList(); data2.newID = newID; data2s.Add(data2); } // カテゴリIDの変更を反映させる foreach(Data2 data2 in data2s) { foreach(Data data in data2.datas) data.Category = data2.newID; } // 変更を反映させる UpdateListViewItems(); } } |
それからカテゴリの機能を追加するということは、メインフォームで[新規][編集]がクリックされたときの処理も変更する必要があるということを意味しています。
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 |
public partial class Form1 : Form { private void buttonNew_Click(object sender, EventArgs e) { RegistForm f = new RegistForm(); foreach(string str in Categories) f.categoryComboBox.Items.Add(str); if(f.ShowDialog() != DialogResult.OK) return; string itemText = f.ItemTextBox.Text; DateTime dt1 = f.deadlineDateTimePicker1.Value; DateTime dt2 = f.deadlineDateTimePicker2.Value; DateTime dt = new DateTime(dt1.Year, dt1.Month, dt1.Day, dt2.Hour, dt2.Minute, dt2.Second); int imp = (int)f.ImportanceNumericUpDown.Value; int cat = f.categoryComboBox.SelectedIndex; string dataString = f.dataStringRichTextBox.Text; Data data = new Data(itemText, dt, imp, cat, dataString); datas.Add(data); UpdateListViewItems(); } private void buttonEdit_Click(object sender, EventArgs e) { Data data = GetDataFromListViewItem(); if(data == null) return; RegistForm f = new RegistForm(); SetDataToRegistForm(f, data); foreach(string str in Categories) f.categoryComboBox.Items.Add(str); if(f.ShowDialog() != DialogResult.OK) return; SetDataFromRegistForm(f, data); UpdateListViewItems(); } } |
これは項目を追加したり編集するときのフォームのクラスです。ロードされたときに必要な処理が追加されました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class RegistForm : Form { public RegistForm() { InitializeComponent(); } // 現在適用されているカテゴリ public int SelectedIndex = 0; // コンボボックスで現在適用されているカテゴリが選択されている状態にする private void RegistForm_Load(object sender, EventArgs e) { if(categoryComboBox.Items.Count > SelectedIndex) categoryComboBox.SelectedIndex = SelectedIndex; } } |
以下はRegistFormクラスにデータをセットしたりデータを取得するメソッドです。
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 |
public partial class Form1 : Form { void SetDataToRegistForm(RegistForm f, Data data) { f.ItemTextBox.Text = data.ItemText; f.deadlineDateTimePicker1.Value = data.Deadline; f.deadlineDateTimePicker2.Value = data.Deadline; f.ImportanceNumericUpDown.Value = data.Importance; f.SelectedIndex = data.Category; f.dataStringRichTextBox.Text = data.DataString; } void SetDataFromRegistForm(RegistForm f, Data data) { data.ItemText = f.ItemTextBox.Text; DateTime dt1 = f.deadlineDateTimePicker1.Value; DateTime dt2 = f.deadlineDateTimePicker2.Value; data.Deadline = new DateTime(dt1.Year, dt1.Month, dt1.Day, dt2.Hour, dt2.Minute, dt2.Second); data.Importance = (int)f.ImportanceNumericUpDown.Value; data.Category = f.categoryComboBox.SelectedIndex; data.DataString = f.dataStringRichTextBox.Text; } void AddListViewItemFromData(Data data) { string itemText = data.ItemText; string deadlineText = data.Deadline.ToString(); string inportanceText = data.Importance.ToString(); string dataString = data.DataString; string category = ""; if(data.Category >= 0) category = Categories[data.Category]; ListViewItem item = new ListViewItem(new string[]{ itemText, deadlineText, inportanceText, category, dataString}); listView1.Items.Add(item); } } |