かずきのBlog@hatena

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

MVVMのVMをF#で実装するとしたら?

こんな基本クラスを用意しておくと記述が楽かも。まぁ同じことはC#でも言えますが。
ネタ元は以下の記事です。

open System
open System.ComponentModel

/// INotifyPropertyChangedの実装
type NotifyObject() =
    let propertyChangedEvent = Event<_, _>()
	
    interface INotifyPropertyChanged with
        [<CLIEvent>]
        member x.PropertyChanged = propertyChangedEvent.Publish
	
    /// プロパティのsetterの実装簡略化用メソッド
    member x.SetProperty((field : 'a byref), (value : 'a), (name : string)) =
        if field = value then
            ()
        else
            field <- value
            propertyChangedEvent.Trigger(x, PropertyChangedEventArgs(name))

/// お試し実装
type HogeViewModel() =
    inherit NotifyObject()
    
    let mutable name = "default value"
    
    member x.Name
        with get() = name
        and set v = x.SetProperty(&name, v, "Name")

// 使ってみる
let vm = HogeViewModel()

// PropertyChangedがちゃんと動いてるか確認用イベントハンドラを登録
let p = vm :> INotifyPropertyChanged
p.PropertyChanged.Add <| fun e -> (printfn "%s property changed" e.PropertyName)

// レッツ代入
vm.Name <- "田中"
printfn "name = %s" vm.Name
vm.Name <- "Tanaka"
printfn "name = %s" vm.Name

実行すると、以下のような結果になります。ちゃんと動いてるくさい。

Name property changed
name = 田中
Name property changed
name = Tanaka

プロパティ名を文字列で指定してるところを、タイプセーフに指定できるようにすればOKだ。F#だと<@ ... @>みたいに書くんだったかな。後で調べよう。