かずきのBlog@hatena

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

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