F#でWPF --- テキストボックスCommand
今回はstringを送るCommandをTextBoxに追加します。
TextBoxにはCommandプロパティが用意されていないため、Behaviorを作成します。
Behaviorの基本は下記記事を参照してください。
F#でWPF --- チェックボックスCommand --- Behavior利用 - 何でもプログラミング
作成するアプリケーション
キーボードのフォーカスが外れた時に、テキストボックスの文字列がテキストブロックに反映されるアプリケーションです。
TextBoxBehavior
LostKeyboradFocusのイベントでCommandを実行するようにします。
ついでにReturnでキーボードのフォーカスが外れるようにします。
BehaviorBaseは下記記事を参照してください。
F#でWPF --- チェックボックスCommand --- Behavior利用 - 何でもプログラミング
type TextBoxBehavior() = inherit BehaviorBase<TextBox>() static member val CommandProperty = DependencyProperty.Register("Command", typeof<ICommand>, typeof<TextBoxBehavior>) member this.Command with get() = this.GetValue(TextBoxBehavior.CommandProperty) :?> ICommand and set(x:ICommand) = this.SetValue(TextBoxBehavior.CommandProperty, x) override this.OnAttached control = [ control.LostKeyboardFocus.Subscribe(fun _ -> if this.Command <> null then this.Command.Execute(control.Text)) // Returnでキーボードフォーカスを外す control.KeyDown.Subscribe(fun x -> if x.Key = Key.Return then Keyboard.ClearFocus()) ]
アプリケーションコード
アプリケーション名はBehaviors.exeでTextBoxBehaviorはnamespace Behaviorsに定義されています。
TextBoxのTextはデフォルトでTwoWayなので、setterにアクセスしないようOneWayにします。
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:Behaviors;assembly=Behaviors" Title="MainWindow" Height="100" Width="200"> <Grid> <TextBox Text="{Binding Text, Mode=OneWay}" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"> <i:Interaction.Behaviors> <local:TextBoxBehavior Command="{Binding SetText}" /> </i:Interaction.Behaviors> </TextBox> <TextBlock Text="{Binding Text}" HorizontalAlignment="Left" Margin="13,37,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> </Grid> </Window>
F#
type Model = { Text : string } type Msg = SetText of string let updateModel model msg = match msg with | SetText x -> { model with Text = x } [<STAThread>] [<EntryPoint>] let main argv = let window = Application.LoadComponent(Uri("MainWindow.xaml", UriKind.Relative)) :?> Window window.DataContext <- DataContext({ Text = "" }, updateModel, id) Application().Run(window) |> ignore 0
EventTriggerとInvokeCommandActionで実装
System.Windows.InteractivityのEventTriggerとInvokeCommandActionを利用してLostKeycoardFocus時にCommandを送ることができます。
またRelativeSourceのFindAncestorモードを利用することにより、TextBoxのTextプロパティをCommandParameterにバインドすることが可能です。
この例ではReturn入力時にキーボードフォーカスが外れることはありません。
<TextBox Text="{Binding Text, Mode=OneWay}" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"> <i:Interaction.Triggers> <i:EventTrigger EventName="LostKeyboardFocus"> <i:InvokeCommandAction Command="{Binding SetText}" CommandParameter="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}}}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBox>