かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

F#用MVVMライブラリを作ってみました

とりあえず勢いだけで作ってCodePlex上に置きました。Prismをベースにしています。

nugetからインストールできるのでKinkumaで検索するとひっかかります。nugetのページは以下になります。

基本的に.NET Framework 4のWPFにしか対応していません。Silverlightはおいおい・・・。

想定

以下のようなプロジェクト構成で使うことを想定しています。

View

C#WPFアプリケーションにKinkumaFrameworkを追加

ViewModel

F#のクラスライブラリにKinkumaFramework.FSharpを追加

Model

F#のクラスライブラリ

コード例

ViewModelのコードを以下に示します。

namespace KinkumaFramework.FSharp.HelloWorld.ViewModel

open System
open System.Windows
open Microsoft.Practices.Prism.Interactivity.InteractionRequest
open Microsoft.Practices.Prism.Commands
open Okazuki.MVVM.PrismSupport.Interactivity
open Okazuki.MVVM.PrismSupport.FSharp
open KinkumaFramework.FSharp.Model

/// MainWindow用のViewModel
type MainViewModel() =
   inherit FsViewModelBase()

   let mutable name = Unchecked.defaultof<string>

   let mutable selected = Unchecked.defaultof<string>

   let mutable alertCommand = Unchecked.defaultof<DelegateCommand>

   let alertRequest = InteractionRequest<ShowMessageBoxConfirmation>()

   /// 名前
   member x.Name
       with get() = name
       and set v = base.SetAndNotify(&name, v, <@ x.Name @>)

   /// 選択結果を表すメッセージ
   member x.Selected
       with get() = selected
       and set v = base.SetAndNotify(&selected, v, <@ x.Selected @>)

   /// Viewへ通知を行うためのInteractionRequest
   member x.AlertRequest = alertRequest

   /// ボタンが押された時のコマンド
   member x.AlertCommad = base.GetOrCreateCommand(&alertCommand, x.AlertExecute, x.CanAlertExecute)

   /// コマンドの処理
   member private x.AlertExecute() =
       async {
           let message = greet x.Name
           let! result = x.AlertRequest.RaiseAsync(
                           ShowMessageBoxConfirmation(
                               Title = "確認", 
                               Content = greet x.Name, 
                               Button = Nullable<MessageBoxButton>(MessageBoxButton.OKCancel)))
           x.Selected <- match result.Confirmed with
                           | true -> "OKが押されました"
                           | false -> "Cancelが押されました"
       } |> Async.StartImmediate

   member private x.CanAlertExecute() = not (String.IsNullOrEmpty(x.Name))

特徴は、プロパティのsetの部分でSetAndNotifyメソッドを呼ぶことで、プロパティのセットから変更通知まで行います。Command型のプロパティではGetOrCreateCommandを使うことでCommandManagerとの連携や必要なCommandのインスタンスの生成などを行います。


また、コールバックが必要なInteractionRequest.Raiseメソッドを非同期ワークフローに対応させました。そのためasync { }の中でRaiseAsyncメソッドを使うことでViewへメッセージを投げて、ViewModelで結果を受け取って続きの処理を行うということを同期的に記述することが出来ます。

ということで、ここ最近もんもんと考えたことをまとめてみました。