F#でWPF --- ファイルダイアログCommand
今回はファイルダイアログを開いて選択されたパスをCommandで送る機能を実装します。
この機能を実装するにあたり、Actionを利用します。
Action
Behaviorと同じく、System.Windows.Interactivity.dllを利用します。
Behaviorの詳細は下記記事を参照してください。
F#でWPF --- チェックボックスCommand --- Behavior利用 - 何でもプログラミング
ActionはTriggerと共に用いられ、例えばボタンがクリックされた時にCommandを実行する記述は下記の様になります。(挙動はButtonのCommandを利用するのと同じです。)
<Button> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding DoSomething}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button>
OpenFileDialogAction
独自のActionを作成するには、TriggerActionを継承しInvoke関数をオーバーライドします。
open System.Windows open System.Windows.Input open System.Windows.Interactivity open Microsoft.FSharp.Linq.NullableOperators open Microsoft.Win32 type OpenFileDialogAction() = inherit TriggerAction<FrameworkElement>() static member val CommandProperty = DependencyProperty.Register("Command", typeof<ICommand>, typeof<OpenFileDialogAction>) member this.Command with get() = this.GetValue(OpenFileDialogAction.CommandProperty) :?> ICommand and set(x:ICommand) = this.SetValue(OpenFileDialogAction.CommandProperty, x) static member val FilterProperty = DependencyProperty.Register("Filter", typeof<string>, typeof<OpenFileDialogAction>) member this.Filter with get() = this.GetValue(OpenFileDialogAction.FilterProperty) :?> string and set(x:string) = this.SetValue(OpenFileDialogAction.FilterProperty, x) override this.Invoke parameter = let dialog = OpenFileDialog(Filter = this.Filter) if dialog.ShowDialog() ?= true && this.Command <> null then this.Command.Execute dialog.FileName
作成するアプリケーション
ボタンを押してファイルダイアログを開き、パスを選択するとテキストボックスにパスが表示されるアプリケーションを作成します。
アプリケーションコード
アプリケーション名はActions.exeです。
OpenFileDialogActionはnamespace Actionsに定義されています。
F#で利用しているDataContextは下記記事を参照してください。
F#でWPF --- Elm Architectureを利用したMVVM - 何でもプログラミング
またF#でWPFプロジェクトを作成する方法は下記記事を参照してください。
F#でWPF --- ウィンドウ表示 - 何でもプログラミング
<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:Actions;assembly=Actions" Title="MainWindow" Height="80" Width="250"> <Grid> <Button Content="ファイルダイアログ" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="100"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <local:OpenFileDialogAction Command="{Binding SetPath}" Filter="F#|*.fs" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> <TextBlock Text="{Binding Path}" HorizontalAlignment="Left" Margin="115,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> </Grid> </Window>
F#
open System open System.Windows type Model = { Path : string } type Msg = SetPath of string let updateModel model msg = match msg with | SetPath x -> { model with Path = x } [<STAThread>] [<EntryPoint>] let main argv = let window = Application.LoadComponent(Uri("MainWindow.xaml", UriKind.Relative)) :?> Window window.DataContext <- DataContext({ Path = "" }, updateModel, id) Application().Run(window) |> ignore 0