【WPF】リファクタリングで学ぶMVVM、Prism。その④ ～ 行削除ボタンのClick処理をリファクタリング ～

# はじめに
下記の記事の続きとなります。

[【WPF】リファクタリングで学ぶMVVM、Prism。その③ ～ 行追加ボタンのClick処理をリファクタリング ～](https://qiita.com/furugen/items/f176bbfe198fdc857052)

この記事は、行削除ボタンのClick処理をリファクタリングしていきます。

# リファクタリングの対象
タイトルにもある通り、行削除ボタンのイベント処理をCommandを利用して、ViewからViewMode/MOdelに責務を移管します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48623/fd7abf4f-60f5-2574-a008-4b3ebdad142f.png)

ソースコードはこちらとなります。

```xml:MainView.xaml
<Button Grid.Column="1" Click="deleteBtnClick">行削除</Button>
```

```csharp:MainWindow.xaml.cs
        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が行っている処理を整理します。
1. 行削除ボタンがクリックされたらdeleteBtnClickメソッドの処理を実行する。
2. XamDataGridからデータソースを取得する。
3. XamDataGridの選択中のレコードを取得する。
4. 取得したデータソースから選択中のレコード削除する。
5. 更新したデータソースを再反映させる。
これらをViewから処理移管していきましょう。

まず行削除ボタンのクリックをViewModelで感知するために、Commandの機能を利用します。あとは、Modelにレコード削除のメソッドを用意してViewModelからコールするようにするればOKです。"選択中のレコード"を取得するためにバインディングを利用してViewModelから選択行のレコード情報が取得できるようにします。

## コードリファクタリング

### 1. XamDataGridの選択行の情報をViewModelから参照できるようにバインディング
行削除の動きとしては、選択行を削除するという仕様でした。リファクタリングにより行削除の処理をViewModelに移管するためには、選択行もViewModelから参照できる必要があります。バインディングを利用して参照できるようにしましょう。

```csharp:MainWindow.xaml.cs
(SampleData)this.xamDataGrid.ActiveDataItem
```
まずは、MainWindowViweModelにバインディングするためのプロパティを新設します。

```csharp:MainWindowViewModel.cs
public SampleData SelectedActiveDataItem { get; set; }
```

次に、ActiveDataItemを新設したプロパティとバインディングを設定します。

```xml:MainView.xaml
<igWPF:XamDataGrid x:Name="xamDataGrid" ...省略...
                   ActiveDataItem="{Binding SelectedActiveDataItem}">
```

これでMainWindowViweModelから選択行の情報が取得できるようになりました。

### 2. 行削除ボタンのクリック時に呼び出されるCommandを作成する。
まずは、ほぼ空のCommandクラスを作成しましょう。

```csharp:RemoveCommand.cs
public class RemoveCommand : ICommand
{
    public bool CanExecute(object parameter) { return true; }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {

    }
}
```

ViewModelを操作できるようコンストラクタで対象のMainWindowViewModelを取得できるようにします。

```csharp:RemoveCommand.cs
    private MainWindowViewModel vm;
    public AddCommand(MainWindowViewModel viewModel)
    {
        this.vm = viewModel;
    }

```

Commandが実行された際に動作するExcuteメソッドで、ViewModel側で用意する行追加メソッドをコールしましょう。OnRemoveRecord()の詳細については、次の項目にて。

```csharp:RemoveCommand.cs
    public void Execute(object parameter)
    {
      this.vm.OnRemoveRecord();
    }
```

### 3. 行削除ボタンのクリックイベントを削除し、2.で作成したCommandをバインディングします。

ViewModelに作成したコマンドをプロパティとして保持し、コンストラクタで初期化します。

```csharp:MainWindowViewModel.cs
        public RemoveCommand RemoveCommand { get; set; }

        public MainWindowViewModel()
        {
            ...省略...
            // 行削除コマンドを追加
            this.RemoveCommand = new RemoveCommand(this);
        }
```

Viewの行追加ボタンをクリックイベントではなく、コマンドで処理するように変更します。先ほどViewModelに追加したRemoveCommandプロパティとバインディングしましょう。

```xml:MainView.xaml
<Button Grid.Column="1" Command="{Binding RemoveCommand}">行削除</Button>
```

これで、行削除ボタンがクリックされた際に、RemoveCommand.Execute()が実行されるようになりました。

### 4. ViewModelの行削除メソッドから、Modelが保持する社員情報削除メソッドをコールします。

コマンド実行時(RemoveCommand.Execute)から呼ばれるメソッドを実装しましょう。

```csharp:MainWindowViewModel.cs
        public void OnRemoveRecord()
        {
            // 社員情報のModelから社員情報を削除する。
            this.employeeServiceModel.RemoveEmployee(this.SelectedActiveDataItem);
        }
```

次に、Modelに社員情報を削除するメソッドを実装します。

```csharp:EmployeeServiceModel.cs
        public void RemoveEmployee(SampleData targetData)
        {
            this.Employees.Remove(targetData);
        }
```

では、実際に動作確認をしてみましょう。行削除ボタンをクリックした際に、XamDataGridの選択行が削除されていることを確認できればOK!!!

![Capture15.gif](https://qiita-image-store.s3.amazonaws.com/0/48623/b34def89-3358-ca67-0d53-47b24d35c085.gif)


## リファクタリング前後のコード
今回のリファクタリング前後のコードはこちらになります。

実施前
https://github.com/furugen/WPF-Try-Refactoring/tree/edition3
実施後
https://github.com/furugen/WPF-Try-Refactoring/tree/edition4

## まとめ
MainWindow.xaml.csの行削除ボタンのClickに伴う処理を責務分割しました。
基本的な作業は、行追加ボタンで行ったリファクタリングと同じ作業でしたね。

次は、編集、編集の確定機能周りをリファクタリングしていきます。

#次の記事

[【WPF】リファクタリングで学ぶMVVM、Prism。その⑤ ～ 編集機能周り ～](https://qiita.com/furugen/items/519e2ccc323a60b03b1e)