はじめに
下記の記事の続きとなります。
【WPF】リファクタリングで学ぶMVVM、Prism。その③ ~ 行追加ボタンのClick処理をリファクタリング ~
この記事は、行削除ボタンのClick処理をリファクタリングしていきます。
リファクタリングの対象
タイトルにもある通り、行削除ボタンのイベント処理をCommandを利用して、ViewからViewMode/MOdelに責務を移管します。
ソースコードはこちらとなります。
<Button Grid.Column="1" Click="deleteBtnClick">行削除</Button>
private void deleteBtnClick(object sender, RoutedEventArgs e)
{
// 選択行を削除する。
List<SampleData> records = this.xamDataGrid.DataSource as List<SampleData>;
records.Remove((SampleData)this.xamDataGrid.ActiveDataItem);
this.xamDataGrid.DataSource = null;
this.xamDataGrid.DataSource = records;
}
リファクタリング
処理詳細を整理
まずは、deleteBtnClickが行っている処理を整理します。
- 行削除ボタンがクリックされたらdeleteBtnClickメソッドの処理を実行する。
- XamDataGridからデータソースを取得する。
- XamDataGridの選択中のレコードを取得する。
- 取得したデータソースから選択中のレコード削除する。
- 更新したデータソースを再反映させる。
これらをViewから処理移管していきましょう。
まず行削除ボタンのクリックをViewModelで感知するために、Commandの機能を利用します。あとは、Modelにレコード削除のメソッドを用意してViewModelからコールするようにするればOKです。"選択中のレコード"を取得するためにバインディングを利用してViewModelから選択行のレコード情報が取得できるようにします。
コードリファクタリング
1. XamDataGridの選択行の情報をViewModelから参照できるようにバインディング
行削除の動きとしては、選択行を削除するという仕様でした。リファクタリングにより行削除の処理をViewModelに移管するためには、選択行もViewModelから参照できる必要があります。バインディングを利用して参照できるようにしましょう。
(SampleData)this.xamDataGrid.ActiveDataItem
まずは、MainWindowViweModelにバインディングするためのプロパティを新設します。
public SampleData SelectedActiveDataItem { get; set; }
次に、ActiveDataItemを新設したプロパティとバインディングを設定します。
<igWPF:XamDataGrid x:Name="xamDataGrid" ...省略...
ActiveDataItem="{Binding SelectedActiveDataItem}">
これでMainWindowViweModelから選択行の情報が取得できるようになりました。
2. 行削除ボタンのクリック時に呼び出されるCommandを作成する。
まずは、ほぼ空のCommandクラスを作成しましょう。
public class RemoveCommand : ICommand
{
public bool CanExecute(object parameter) { return true; }
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
}
ViewModelを操作できるようコンストラクタで対象のMainWindowViewModelを取得できるようにします。
private MainWindowViewModel vm;
public AddCommand(MainWindowViewModel viewModel)
{
this.vm = viewModel;
}
Commandが実行された際に動作するExcuteメソッドで、ViewModel側で用意する行追加メソッドをコールしましょう。OnRemoveRecord()の詳細については、次の項目にて。
public void Execute(object parameter)
{
this.vm.OnRemoveRecord();
}
3. 行削除ボタンのクリックイベントを削除し、2.で作成したCommandをバインディングします。
ViewModelに作成したコマンドをプロパティとして保持し、コンストラクタで初期化します。
public RemoveCommand RemoveCommand { get; set; }
public MainWindowViewModel()
{
...省略...
// 行削除コマンドを追加
this.RemoveCommand = new RemoveCommand(this);
}
Viewの行追加ボタンをクリックイベントではなく、コマンドで処理するように変更します。先ほどViewModelに追加したRemoveCommandプロパティとバインディングしましょう。
<Button Grid.Column="1" Command="{Binding RemoveCommand}">行削除</Button>
これで、行削除ボタンがクリックされた際に、RemoveCommand.Execute()が実行されるようになりました。
4. ViewModelの行削除メソッドから、Modelが保持する社員情報削除メソッドをコールします。
コマンド実行時(RemoveCommand.Execute)から呼ばれるメソッドを実装しましょう。
public void OnRemoveRecord()
{
// 社員情報のModelから社員情報を削除する。
this.employeeServiceModel.RemoveEmployee(this.SelectedActiveDataItem);
}
次に、Modelに社員情報を削除するメソッドを実装します。
public void RemoveEmployee(SampleData targetData)
{
this.Employees.Remove(targetData);
}
では、実際に動作確認をしてみましょう。行削除ボタンをクリックした際に、XamDataGridの選択行が削除されていることを確認できればOK!!!
リファクタリング前後のコード
今回のリファクタリング前後のコードはこちらになります。
実施前
https://github.com/furugen/WPF-Try-Refactoring/tree/edition3
実施後
https://github.com/furugen/WPF-Try-Refactoring/tree/edition4
まとめ
MainWindow.xaml.csの行削除ボタンのClickに伴う処理を責務分割しました。
基本的な作業は、行追加ボタンで行ったリファクタリングと同じ作業でしたね。
次は、編集、編集の確定機能周りをリファクタリングしていきます。
#次の記事