【WPF】リファクタリングで学ぶMVVM、Prism　ー　はじめに

# はじめに
WPF、MVVM、Prismのそれぞれの技術要素を、既に作成されたアプリケーションをリファクタリングを行いながら、体系的に学んでいければという記事となります。
リファクタリングを行ううえで最小限の項目しか扱いませんので、WPFやPrismの内容を詳細に学んでいく、とい趣旨ではないことをご了承ください。
※サンプルで用いているコンポーネントは[Infragistics社のWPF製品](https://jp.infragistics.com/products/wpf)を採用している箇所がありますので、動作をお試しいただく際にはコンポーネントのインストールが必要(Trial版あり)となります。

# どんなアプリケーションをリファクタリング？
社員情報を管理するような簡単なアプリケーションを作りました。取り扱う情報としては、名前、年齢という基本的な項目のみ。
![Capture.gif](https://qiita-image-store.s3.amazonaws.com/0/48623/23791dcb-d119-5fe1-12cd-31c75cd77dd2.gif)

## 仕様


- 左側のエリアにて、
    - 社員情報一覧を表示
    - レコードの増減は、"行追加","行削除"のボタンより実行
- 右側のエリアに、
    - 社員情報を修正するエリア(XamPropertyGrid)が表示
    - 編集した内容は'編集内容を確定"にて実行

## ソースコード

 - バインディングを一切行わらず
 - すべてイベントのみで処理し、
 - 主要な実装は MainWindow.xaml / MainWindow.xaml.cs の2ファイルのみ
です。

```xml:MainWindow.xaml
<Window xmlns:igWPF="http://schemas.infragistics.com/xaml/wpf"  xmlns:ig="http://schemas.infragistics.com/xaml"  x:Class="TryRefactoring.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TryRefactoring"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="900">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <!-- 一覧エリア -->
        <StackPanel  Grid.Column="0" Margin="10">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Button Grid.Column="0" Click="addBtnClick">行追加</Button>
                <Button Grid.Column="1" Click="deleteBtnClick">行削除</Button>
            </Grid>
            <igWPF:XamDataGrid x:Name="xamDataGrid" RecordActivated="XamDataGrid_RecordActivated" Height="300">
                <igWPF:XamDataGrid.FieldSettings>
                    <igWPF:FieldSettings AllowEdit="False" />
                </igWPF:XamDataGrid.FieldSettings>
            </igWPF:XamDataGrid>
        </StackPanel>

        <!-- 編集エリア -->
        <StackPanel Grid.Column="1" Margin="10">
            <Button Click="fixBtnClick">編集内容を確定</Button>
            <ig:XamPropertyGrid  x:Name="xamPropGrid" />
        </StackPanel>

    </Grid>
</Window>

```
```csharp:MainWindow.xaml.cs
namespace TryRefactoring
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private string JSON_FILE_PATH = "./Assets/sampledata.json";

        public MainWindow()
        {
            InitializeComponent();

            // Jsonをシリアライズ化してサンプルデータを設定
            this.xamDataGrid.DataSource = LoadJsonFile();
        }

        private List<SampleData> LoadJsonFile()
        {
            // Jsonファイルを読み込み、デシリアライズ化し、SampleDataに設定します。
            string fileContent = System.IO.File.ReadAllText(JSON_FILE_PATH);
            return JsonConvert.DeserializeObject<List<SampleData>>(fileContent);
        }

        private void addBtnClick(object sender, RoutedEventArgs e)
        {
            // 行を追加する
            List<SampleData> records = this.xamDataGrid.DataSource as List<SampleData>;
            records.Add(new SampleData());
            this.xamDataGrid.DataSource = null;
            this.xamDataGrid.DataSource = records;
        }

        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;
        }


        private void fixBtnClick(object sender, RoutedEventArgs e)
        {
            SampleData editData = this.xamPropGrid.SelectedObject as SampleData;
            List<SampleData> records = this.xamDataGrid.DataSource as List<SampleData>;
            SampleData targetData = records.First(data => data.Id == editData.Id);

            // 編集内容を反映
            targetData.Age = editData.Age;
            targetData.Name = editData.Name;

            // XamDataGridに反映
            this.xamDataGrid.DataSource = null;
            this.xamDataGrid.DataSource = records;

            // データソース反映時に選択行が解除されるため、再設定
            this.xamDataGrid.SelectedDataItem = targetData;

        }

        private void XamDataGrid_RecordActivated(object sender, Infragistics.Windows.DataPresenter.Events.RecordActivatedEventArgs e)
        {
            // 選択行のオブジェクトをXamPropertyGridに表示
            xamPropGrid.SelectedObject = this.xamDataGrid.ActiveDataItem;
        }

    }
}
```



### ファイル構成
TryRefactoring
 │  MainWindow.xaml
 │  MainWindow.xaml.cs
 ├─Assets
 │      sampledata.json
 ├─Data
 │      SampleData.cs

**GitHub**はこちら。
https://github.com/furugen/WPF-Try-Refactoring/tree/edition1
 


# どうやってリファクタリングしていく？
まずは、MVVMの土台を作成し、適切なコントロールの分割化。そのあとにPrismとしての最適化を行っていきます。
各項目については、目次をご参照くださいませ。

# 目次(予定)
WPF標準機能 + MVVM あれこれ
1. バインディング (View)(ViewModel)(Model)
2. ViewModel,Modelの作成 (View)(ViewModel)
3. ユーザコントロールの分割 (View)(ViewModel)
4. イベントのコマンド化 (ViewModel)

Prism
5. Prism導入
6. Region
7. Module化

# まとめ
次の記事から目次のメニューを消化していき、MVVM,Prism向けにリファクタリングしていきます。
まずは、ViewModelの外枠から作っていきますよー。

#次の記事

[【WPF】リファクタリングで学ぶMVVM、Prism。その① ～ ＭＶＶＭ観点で処理を切り分ける ～](https://qiita.com/furugen/items/7d64b56f0d1b31db06a1)