前回は、編集系のメソッドの動きをIEditableObjectとそうじゃない場合で見てみた。
今回は、新規追加系のメソッドの動きを、IEditableObjectとそうじゃない場合で見ていこうと思う。
編集対象のクラスは、前回と同じPersonクラスとEditablePersonクラスを使います。一応前回と同じだけどコードだけ再掲します。
public class Person
{
public string Name { get; set; }
public override string ToString()
{
return "Person: Name = " + Name;
}
}
public class EditablePerson : Person, IEditableObject
{
private EditablePerson back;
#region IEditableObject メンバ
public void BeginEdit()
{
Console.WriteLine("# BeginEdit Called: " + this);
back = (EditablePerson)MemberwiseClone();
}
public void CancelEdit()
{
Console.WriteLine("# CancelEdit Called: " + this);
if (back == null)
{
return;
}
Name = back.Name;
}
public void EndEdit()
{
Console.WriteLine("# EndEdit Called: " + this);
back = null;
}
#endregion
}
基本的にNameプロパティを持つだけの、シンプルなクラスです。EditablePersonは、MemberwiseCloneを使ってバックアップ用のオブジェクトを作って、CancelEdit時にデータを書き戻すことをやっています。
このクラスに加えて、これから書くプログラム内で、IEditableCollectionViewの新規追加に関係するプロパティをコンソールに出力するためにDumpメソッドというものも適当に定義してあります。
private static void Dump(string msg, IEditableCollectionView editableView)
{
Console.WriteLine("------------------------------");
Console.WriteLine(" " + msg);
Console.WriteLine(" IEditableCollectionView");
Console.WriteLine(" :CanAddNew: " + editableView.CanAddNew);
Console.WriteLine(" :IsAddingNew: " + editableView.IsAddingNew);
Console.WriteLine(" :CurrentAddItem: " + editableView.CurrentAddItem);
Console.WriteLine(" :Count: " + ((CollectionView)editableView).Count);
}
新規追加が可能なのか?現在新規追加中なのか?現在新規追加中のオブジェクトは何か?という情報に加えて、現在コレクションに何件入っているかといった情報を表示しています。
これで、下準備完了。Mainに、下のようなプログラムを書いて動きを確認してみます。
// テスト用のListCollectionViewを作成(2件のデータ)
// とりあえず、IEditableObjectじゃない普通のPersonクラスで
var people = Enumerable.Range(1, 2).Select(i =>
new Person { Name = "田中 太郎" + i }).ToList();
var view = CollectionViewSource.GetDefaultView(people);
// IEditableCollectionViewにキャストするよ
var editableView = (IEditableCollectionView)view;
// 追加前の状態を表示
Dump("追加前", editableView);
// 追加処理開始
Console.WriteLine("Before AddNew");
var newObject = editableView.AddNew() as Person;
Console.WriteLine("After AddNew");
// 名前の入力
Console.WriteLine("追加する人の名前を入力してください");
Console.Write("#> ");
newObject.Name = Console.ReadLine();
Dump("追加確定前", editableView);
// 追加の確定・キャンセル
Console.WriteLine("追加してよろしいですか?(Y/N)");
Console.Write("#> ");
string answer = Console.ReadLine();
if (answer == "Y")
{
Console.WriteLine("Before CommitNew");
editableView.CommitNew();
Console.WriteLine("After CommitNew");
}
else
{
Console.WriteLine("Before CancelNew");
editableView.CancelNew();
Console.WriteLine("After CancelNew");
}
Dump("追加確定後", editableView);
とりあえず、IEditableObjectじゃない通常のPersonクラスのリストを作って編集しています。
最初に作ったダミーデータは2件なので、追加完了後には3件になっているはず。
追加前・追加処理中・追加後でどのようにIEditableCollectionViewのプロパティの値が変わってるかが確認のポイントです。
ということで、普通に新規追加する場合の操作をしたときの実行結果を以下に示します。
------------------------------
追加前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
Before AddNew
After AddNew
追加する人の名前を入力してください
#> Tanaka Taro
------------------------------
追加確定前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: True
:CurrentAddItem: Person: Name = Tanaka Taro
:Count: 3
追加してよろしいですか?(Y/N)
#> Y
Before CommitNew
After CommitNew
------------------------------
追加確定後
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 3
AddNewメソッドを呼び出すと、IsAddingNewプロパティがFalseからTrueに、CurrentAddItemがnullから追加されたインスタンスに変わっているのがわかる。
Countプロパティも、2から3に増えている。
CommitNewの後は、IsAddingNewがFalse, CurrentAddItemがnullに戻っている。
次に、追加処理をキャンセルする場合の実行結果を以下に示す。
------------------------------
追加前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
Before AddNew
After AddNew
追加する人の名前を入力してください
#> 田中 太郎
------------------------------
追加確定前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: True
:CurrentAddItem: Person: Name = 田中 太郎
:Count: 3
追加してよろしいですか?(Y/N)
#> N
Before CancelNew
After CancelNew
------------------------------
追加確定後
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
途中まで、動きは一緒だけど、キャンセルするとCountプロパティが3に増えずに2のままになってるのがわかる。
特に難しい動きはしていない。新規追加に限ってしまえば、IEditableObjectじゃなくても特に制限はなさそうな感じに見える。
EditItemのときは、IEditableObjectじゃないとキャンセルが出来なかったが、新規追加はキャンセルしても問題ない。
一応IEditableObjectのときの動きも確認しておこうと思う。
プログラムの先頭部分でPersonのリストを生成していた処理を以下のように書き換えてEditablePersonを作るようにする。
// テスト用のListCollectionViewを作成(2件のデータ)
var people = Enumerable.Range(1, 2).Select(i =>
new EditablePerson { Name = "田中 太郎" + i }).ToList();
この状態で、新規追加をする場合の実行結果を見てみた。
------------------------------
追加前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
Before AddNew
# BeginEdit Called: Person: Name =
After AddNew
追加する人の名前を入力してください
#> Tanaka Taro
------------------------------
追加確定前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: True
:CurrentAddItem: Person: Name = Tanaka Taro
:Count: 3
追加してよろしいですか?(Y/N)
#> Y
Before CommitNew
# EndEdit Called: Person: Name = Tanaka Taro
After CommitNew
------------------------------
追加確定後
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 3
基本的にPersonクラスのときとかわらないけど、AddNewメソッドとCommitNewメソッドの呼出しのタイミングでIEditableObjectのBeginEditとEndEditメソッドが呼び出されている。
続いて、新規追加をキャンセルする場合の動作結果を見てみる。
------------------------------
追加前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
Before AddNew
# BeginEdit Called: Person: Name =
After AddNew
追加する人の名前を入力してください
#> Tanaka Taro
------------------------------
追加確定前
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: True
:CurrentAddItem: Person: Name = Tanaka Taro
:Count: 3
追加してよろしいですか?(Y/N)
#> N
Before CancelNew
# CancelEdit Called: Person: Name = Tanaka Taro
After CancelNew
------------------------------
追加確定後
IEditableCollectionView
:CanAddNew: True
:IsAddingNew: False
:CurrentAddItem:
:Count: 2
こちらも、基本的に同じだけど、AddNewとCancelNewの呼出しのタイミングで、IEditableObjectのBeginEditと、CancelEditが呼び出されている。
新規追加の場合に意味があるかといわれるとどうだろう?といった感じだけど連携してる感がある。
ということで、追加の場合の動きを簡単にまとめると下のような感じになる。
AddNewメソッドで新規登録処理を開始する。戻り値が登録されるインスタンスになる。
IsAddItemNewメソッドで新規登録してる最中かどうかを確認する。
CommitAddNewとCancelAddNewメソッドで確定、キャンセルをする。