KB)WPFの最大の特長といえば、UIとコマンドロジックを分離できるMVVM(Model-View-ViewModel)パターンでのアプリケーション開発が可能であることです。MVVMは、WPFだけではなくモバイルアプリやUWPでも適用でき、MVVMの発表から10年以上経つ現在も注目されています。WPFでももちろんMVVMの利用をサポートしています。WPFを用いて、MVVMパターンを使用したアプリケーションを作成する方法を紹介します。WPFとは累計販売ライセンス140,000本を超え、グレープシティを代表する製品の一つ「SPREAD」シリーズのWPF向けコンポーネントです。SPREADの最大の特長であるExcelライクな外観や操作性のほか、1レコード複数行表示やグループ集計など、独自機能も備えます。詳しい機能は、製品情報サイトで紹介しておりますので、是非ご一読ください。ClickOnceデモも公開しています。1.0Jの製品版またはトライアル版のインストールが必要です。トライアル版はこちらからダウンロードしていただけます。1.0J」で詳しく解説されていますので、そちらをご覧ください。サンプルアプリケーションの概要コード、製品名、価格というフィールドを持った製品データ一覧をSPREADに表示し、SPREADのボタン型セルを使用してコマンドを実行するという簡単なWPFアプリケーションを、MVVMパターンで作成します。データをSPREADに表示する(1)まずは、製品データを単純にSPREADに表示するだけのアプリケーションを作成しましょう。SpreadWPF_MVVMという名前で新規プロジェクトを作成します。モデルを作成ここでは、単純にデータをモデル化したものをモデルとして定義します。ProductModelという名称のクラスを作成し、製品(コード、名称、価格)データのコレクションを生成、そのコレクションを返すメソッドを用意します。データコレクションを返します。次に、ビューモデルに該当するクラスをProductViewModelという名称で、新規に作成します。ビューモデルクラスは値が変更された場合に、ビューに変更を通知するため、INotifyPropertyChangedインタフェースを実装します。データをSPREADに表示するだけですので、モデルからデータを取得します。ビューモデルにプロパティとして定義されるデータコレクションにデータが取得されると、ビューに通知が行くという仕組みです。モデルからデータを取得します。ビューに値の変更を通知します。値が変更されるとビューに変更を通知します。次の名前空間宣言を追加しています。モデルからデータを取得します。Viewに値の変更を通知します。値が変更されるとビューに変更を通知します。最後にビューに該当するUIを作成します。Studioのデザイン画面で開き、ツールボックスからSPREAD(gcSpreadGrid1)を配置します。ツールボックスからSPREADを配置WindowのDataContextプロパティにビューモデルを設定し、GcSpreadGridクラスのItemSourceプロパティに、ProductViewModelクラスで定義したデータコレクションにバインドします。備考XAMLコードでは、次のような名前空間を宣言しています。</sg:GcSpreadGrid></StackPanel>コードビハインドでも実装できます。この呼び出しはデザイナーで必要です。SPREADとビューモデルのデータコレクションをバインドします。SPREADとビューモデルのデータコレクションをバインドします。binding1);}ビューでの設定は以上です。モデルで定義されたデータがビューモデルを介してビューに表示されるようになります。上記のコードを実行すると次のような画面となります。MVVMパターンでデータ表示したSPREADSPREADには連結するデータのデータフィールドを自動的に列として生成する機能があります。既定では列の自動生成が有効になっているため、上記のように連結したデータはすべてSPREADに表示されます。特定のデータ列のみ表示したい場合は、列の自動生成機能を無効にし、列のDataFieldプロパティを使用してデータソースのフィールドに関連付けます。列の自動生成機能は、GcSpreadGridクラスのAutoGenerateColumnsプロパティをfalseに設定すると無効となります。次のコードでは、「Price」列のみ非表示にします。</sg:GcSpreadGrid></StackPanel>コードビハインドでの同じ設定は、以下のようなコードで可能です。次の名前空間宣言を追加しています。この呼び出しはデザイナーで必要です。呼び出しの後で初期化を追加します。列の自動生成を無効にします。Code、Name列のみ表示します。SPREADとビューモデルのデータコレクションをバインドします。次の名前空間宣言を追加しています。列の自動生成を無効にします。Code、Name列のみ表示します。SPREADとビューモデルのデータコレクションをバインドします。備考ここでは特に表示列数の指定はしていないため、既定の10列が表示されます。コマンドを作成する現時点で、SPREADには「Code」と「Name」のデータだけが表示されていますので、選択された製品の「Price」を取得するというコマンドを作成しましょう。側でコマンドをバインディングできるのは、基本的にMenuItemやButtonといったICommandインタフェースを実装したコントロールです。SPREADでは、ボタン型セルにコマンド機能を設定することができます。ボタン型セルのCommandプロパティは、依存関係プロパティではないため、ビューモデルのプロパティとして公開されたコマンドに直接バインドすることはできません。そこで、ボタン型セルに設定するカスタムコマンドのパラメータに、ビューで作成したビューモデルのインスタンスを渡す方法を紹介します。ビューモデルにプロパティを追加ProductViewModelクラスにビューとバインディングするデータをプロパティとして追加します。ここでは、選択された製品「SelectedProduct」と、製品名「ProductName」、価格「ProductPrice」の3つのプロパティを追加し、それぞれビューに変更が通知されるよう、OnPropertyChangedメソッドを実装します。次に、選択された製品から、製品名と価格を取得するコマンドを実装します。コマンドはICommandインタフェースを実装します。ボタン型セルにコマンドを設定すると、Executeメソッドのパラメータからは、セルの情報を保存したCellCommandParameterオブジェクトを取得できます。CellCommandParameterクラスのCustomCommandParameterプロパティには、任意の情報を保存できます。ここでは、ProductViewModelオブジェクトを保存し、ビューモデルクラスのメンバにアクセスできるようにします。次の名前空間宣言を追加しています。CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。ビューモデルのプロパティを更新します。次の名前空間宣言を追加しています。CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。ビューモデルのプロパティを更新します。}}ビューのコントロールにバインディング最後に、ビューモデルで定義したプロパティや、コマンドをビューのコントロールにバインディングします。選択された製品の製品名と値段を表示する、TextBlockコントロールを次のように定義します。TextプロパティにProductViewModelクラスのProductNameとProductPriceプロパティをバインディングしています。VerticalAlignment="Bottom"/></StackPanel>次に、SPREADで選択された項目とProductViewModelクラスのSelectedProductプロパティをバインドします。SPREAD側での値選択がトリガーとなる双方向バインディングであるため、ModeプロパティはTwoWayにします。</sg:GcSpreadGrid.Columns></sg:GcSpreadGrid>コードビハインドでの同じ設定は、以下のようなコードで可能です。選択行にViewModelのSelectedProductプロパティをバインドします。選択行にViewModelのSelectedProductプロパティをバインドします。selectedBinding);そして、SPREADのボタン型セルにコマンドを設定します。ここでは、3列目にボタン型セルを設定します。ButtonCellTypeオブジェクトを作成し、CommandプロパティにはGetPriceCommandを、CustomCommandParameterプロパティには、ProductViewModelクラスのインスタンスを設定します。ボタン型セルの設定は、コードビハインドの方がわかりやすいです。列の自動生成を無効にします。Code、Name列のみ表示します。SPREADとビューモデルのデータコレクションをバインドします。選択行にビューモデルのSelectedProductプロパティをバインドします。ボタン型セルを作成します。ボタンにコマンドを設定します。列の自動生成を無効にします。Code、Name列のみ表示します。SPREADとビューモデルのデータコレクションをバインドします。選択行にビューモデルのSelectedProductプロパティをバインドします。ボタン型セルを作成します。ボタンにコマンドを設定します。button;}XAMLでボタン型セルにコマンドを設定するには、コマンドをリソースとして定義します。DataContextに設定しているProductViewModelクラスに名前をつけて、CustomCommandParameterプロパティに設定します。</sg:GcSpreadGrid></StackPanel>以上で完成です。実行し、知りたい製品の「値段」ボタンをクリックすると、次のように表示されます。コマンドの実行コマンドでSPREADを操作するSPREADの行、列、セルを生成するRow、Column、Cellクラスのメンバは、依存関係プロパティを持っていません。そのため、これらのクラスのメンバをバインディングターゲットとすることができず、ビューモデルからセルや列に対して直接バインディングができません。ボタン型セルに設定したコマンドが実行されると、Executeメソッドのパラメータからは、セルの情報を保存したCellCommandParameterオブジェクトを取得できます。コマンドクラスにSPREADオブジェクトを示すプロパティを追加することで、コマンドによりSPREADを操作できるようになります。ここでは、そのテクニックについて紹介します。「値段」ボタン型セルのクリックで、4列目に値段を表示し、さらに値段が300円以上の場合は、行の背景色を変更するというコマンドを作成します。コマンドを変更する先ほど作成したGetPriceCommandクラスを変更します。GcSpreadGridオブジェクトを示すプロパティを追加します。}}次に、Executeメソッドを変更します。パラメータ「parameter」から、ボタンが押されたセル情報を格納しているCellCommandParameterクラスを取得できます。CellCommandParameterクラスのCellPositionプロパティからボタンが押されたセルの行インデックスを取得できるため、変更を行いたいSPREADの行にアクセスすることができます。CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。ビューモデルのプロパティを更新します。ボタン型セルの右側のセルに価格を表示します。ボタン型セルの右側のセルに価格を表示します。価格が300円以上のものは、行の背景色を変更します。CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。ビューモデルのプロパティを更新します。ボタン型セルの右側のセルに価格を表示します。価格が300円以上のものは、行の背景色を変更します。}}最後に、ビューでボタン型セルを生成するとき、Commandプロパティに設定するGetPriceCommandオブジェクトのspreadプロパティにGcSpreadGridオブジェクトを設定します。ボタン型セルを作成します。ボタンにコマンドを設定します。ボタン型セルを作成します。ボタンにコマンドを設定します。button;XAMLでは、リソースとして定義したコマンドを次のように実装します。/></Window.Resources>アプリケーションを実行し、いくつかボタン型セルをクリックすると、次のような結果となります。コマンドでSPREADを操作コマンドのコンストラクタ引数を使用するコマンドクラスから、ビューモデルやSPREADオブジェクトへアクセスする方法として、CustomCommandParameterプロパティの使用や、コマンドクラスへのプロパティ追加を紹介しましたが、この他に、コマンドクラスのコンストラクタ引数にオブジェクトを渡す方法も考えられます。XAMLにはコンストラクタに引数を渡す方法が用意されていないため、この方法はコードビハインドでの設定のみ有効です。コマンドを定義するGetPriceCommandクラスを次のように実装します。SPREADとビューモデルを示すプロパティを定義します。ビューモデルのプロパティを更新します。ボタン型セルの右側のセルに価格を表示します。価格が300円以上のものは、行の背景色を変更します。SPREADとビューモデルを示すプロパティを定義します。//ビューモデルのプロパティを更新します。ボタン型セルの右側のセルに価格を表示します。価格が300円以上のものは、行の背景色を変更します。}}ビュー側のボタン型セルの設定は、以下の通りです。Commandプロパティに設定するGetPriceCommandクラスのコンストラクタ引数に、SPREADオブジェクトとビューモデルのオブジェクトを渡します。ボタン型セルを作成します。ボタンにコマンドを設定します。ボタン型セルを作成します。ボタンにコマンドを設定します。button;以上で、前項と同様の動作を実現することができます。WPFを使用して、シンプルなMVVMアプリケーションを作成する方法を紹介しました。WPFは、グリッドでありながら標準のDataGridやListBoxコントロールと異なり、ItemTemplateを持たないため、セルや行といった項目単位でバインディングすることができません。SPREADの持つ機能を利用して工夫することで、さまざまなコマンドを実装することも可能です。MVVMパターンの実装方法は多様で、実際の業務アプリケーションでは、もっと複雑な処理が必要となりますが、本記事での基本的な実装紹介が開発の一助となれば幸いです。スプレッドチーム)宮城県仙台市に本社を構えるグレープシティでは、日本の業務に適したシステムをより早く開発するためのソフトウェアを提供しています。エンドユーザーの利用しやすさ、幅広いユーザー環境への対応、そして何よりプログラマの作業を軽減することを一番に目指しています。圧縮・解凍UNIX基本講座@CodeZine『CodeZine(コードジン)』の公式アカウントです。【NEW】デブスト2019デブサミ2019福岡・関西デブサミ2019夏デブスト関西デブサミ2019×ログインEメールパスワード※旧SEメンバーシップ会員の方は、同じ登録情報(Eメール&パスワード)でログインいただけます。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。