F#でWPF --- メッセージボックス

作成するアプリケーション

ボタンを押すと"Hello"のメッセージボックスが表示されるアプリケーションを作成します。
f:id:any-programming:20170206231614p:plain

MVVMを用いない場合

下記の様なシンプルなコードになります。

しかしViewが分離できていません。

button.Click |> Event.add (fun _ -> MessageBox.Show("Hello"))


MVVM化

ViewModelのMessageプロパティが変更されたらViewがMessageBox.Showを呼ぶ実装にします。
f:id:any-programming:20170206233126p:plain

MessageDialogBehavior

上記機能を実現するためにBehaviorを利用します。

BehaviorBaseは下記記事を参照してください。
F#でWPF --- チェックボックスCommand --- Behavior利用 - 何でもプログラミング

open System.Windows
open System.Windows.Input

type MessageDialogBehavior() =
    inherit BehaviorBase<Window>()
    static member val MessageProperty = DependencyProperty.Register("Message", typeof<string option>, typeof<MessageDialogBehavior>)
    member this.Message with get()                = this.GetValue(MessageDialogBehavior.MessageProperty) :?> string option
                        and  set(x:string option) = this.SetValue(MessageDialogBehavior.MessageProperty, x)
    
    static member val ClosedProperty = DependencyProperty.Register("Closed", typeof<ICommand>, typeof<MessageDialogBehavior>)
    member this.Closed with get()           = this.GetValue(MessageDialogBehavior.ClosedProperty) :?> ICommand
                       and  set(x:ICommand) = this.SetValue(MessageDialogBehavior.ClosedProperty, x)

    override this.OnAttached control =        
        [ DependencyProperty.changed<string option> MessageDialogBehavior.MessageProperty this 
          |> Observable.subscribe (Option.iter (fun x -> MessageBox.Show(x) |> ignore
                                                         if this.Closed <> null then
                                                            this.Closed.Execute())) ] 


アプリケーションコード

アプリケーション名はBehaviors.exeです。

MessageDialogBehaviorはnamespace Behaviorsに定義されています。

F#で利用しているDataContextは下記記事を参照してください。
F#でWPF --- Elm Architectureを利用したMVVM - 何でもプログラミング

またF#でWPFプロジェクトを作成する方法は下記記事を参照してください。
F#でWPF --- ウィンドウ表示 - 何でもプログラミング

Xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
        xmlns:local="clr-namespace:Behaviors;assembly=Behaviors"
        Title="MainWindow" Height="100" Width="200">
    <i:Interaction.Behaviors>
        <local:MessageDialogBehavior Message="{Binding Message}" Closed="{Binding ClearMessage}" />
    </i:Interaction.Behaviors>
    <Grid>
        <Button Content="メッセージボックス" Command="{Binding ShowMessage}" HorizontalAlignment="Left" Margin="40,20,0,0" VerticalAlignment="Top" Width="100" />
    </Grid>
</Window>

F#

open System
open System.Windows

type Model = { Message : string option }

type Msg = 
    | ShowMessage
    | ClearMessage

let updateModel model msg =
    match msg with
    | ShowMessage -> 
        { model with Message = Some "Hello" }

    | ClearMessage ->
        { model with Message = None }

[<STAThread>]
[<EntryPoint>]
let main argv = 
    let window = Application.LoadComponent(Uri("MainWindow.xaml", UriKind.Relative)) :?> Window
    window.DataContext <- DataContext({ Message = None }, updateModel, id)
    Application().Run(window) |> ignore   
    0