かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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で結果を受け取って続きの処理を行うということを同期的に記述することが出来ます。

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