かずきのBlog@hatena

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

F#でMVVM Light Toolkit

フルF#(XAML無し)で組んでみました。後悔しています。とりあえずやるもんじゃないですね!でも、せっかく書いたのでメモメモ。

#if INTERACTIVE
#r "PresentationCore.dll"
#r "PresentationFramework.dll"
#r "WindowsBase.dll"
#r "GalaSoft.MvvmLight.Extras.WPF4.dll"
#r "GalaSoft.MvvmLight.WPF4.dll"
#r "Microsoft.Expression.Interactions.dll"
#r "System.Windows.Interactivity.dll"
#r "System.Xaml.dll"
#r "UIAutomationTypes.dll"
#endif

open System
open System.Windows
open System.Windows.Controls
open System.Windows.Data
open GalaSoft.MvvmLight
open GalaSoft.MvvmLight.Command

// ViewModelはすっきりな感じ?
type MainViewModel() =
    inherit ViewModelBase()
    let mutable message = "init"

    member x.Message
        with get() = message
        and set(v) = 
            message <- v
            base.RaisePropertyChanged("Message")

    member private x.Greet =
        x.Message <- DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + "にこんにちは"

    member x.GreetCommand = RelayCommand(fun() -> x.Greet)

// ViewModelのロケータ(MVVM Lightの作法?)
type ViewModelLocator() =
    member x.Main = MainViewModel()

// メインのView。XAMLが恋しい…
type MainView() as x =
    inherit Window(Title = "Hello world F#", Width = 250., Height = 250.)
    let grid1 = Grid()
    let button1 = Button(Content = "OK")
    let textBlock1 = TextBlock()
    do
        base.Content <- grid1
        grid1.RowDefinitions.Add <| RowDefinition(Height = GridLength.Auto)
        grid1.RowDefinitions.Add <| RowDefinition(Height = GridLength.Auto)

        Grid.SetRow(textBlock1, 1)
        grid1.Children.Add(button1) |> ignore
        grid1.Children.Add(textBlock1) |> ignore

        textBlock1.SetBinding(
            TextBlock.TextProperty,
            "Message") |> ignore

        button1.SetBinding(
            Button.CommandProperty,
            "GreetCommand") |> ignore
        
        x.SetBinding(Window.DataContextProperty,
            Binding("Main", Source = Application.Current.Resources.["Locator"])) |> ignore

// アプリケーションクラス
type App() as x =
    inherit Application()
    let locator = ViewModelLocator()
    do
        // locatorをリソースに登録
        x.Resources.Add("Locator", locator)
        // 開始時にMainViewを表示
        x.Startup.Add <| fun e ->
            let w = MainView()
            w.Show()

[<STAThread>]
do
    // アプリスタート!!
    let app = App()
    app.Run() |> ignore