📷
Avalonia.FuncUI.Elmishでフォーカス制御
Avalonia.FuncUIでTextBoxなどのフォーカスを制御する方法についての記事です。
公式のCommon QuestionsにComponentsでのサンプルコードはあるのですが、Elmishで同じことをするにはどうすればいいのかがわからず、ググっても出ず、ChatGPTに尋ねれば存在しない関数を回答するなど、かなり右往左往してしまいました。
View.withOutlet関数でそのコントロールの参照が取れるので、それを使えばよいだけでした...
open Avalonia.FuncUI.DSL
open Avalonia.Controls
open Avalonia.Layout
open Avalonia.Media
type State = {
textBoxAFocus: bool
textBoxBFocus: bool
}
let init () = {
textBoxAFocus = false
textBoxBFocus = false
}
type Msg =
| TextBoxAFocusChanged of bool
| TextBoxBFocusChanged of bool
let mutable textBoxA = None
let mutable textBoxB = None
let update msg state =
match msg with
| TextBoxAFocusChanged focus -> { state with textBoxAFocus = focus }
| TextBoxBFocusChanged focus -> { state with textBoxBFocus = focus }
let view (state: State) dispatch =
StackPanel.create [
StackPanel.margin 10
StackPanel.spacing 10
StackPanel.children [
TextBox.create [
TextBox.onGotFocus (fun _ -> TextBoxAFocusChanged true |> dispatch)
TextBox.onLostFocus (fun _ -> TextBoxAFocusChanged false |> dispatch)
]
|> View.withOutlet (fun tb -> textBoxA <- Some tb)
TextBox.create [
TextBox.onGotFocus (fun _ -> TextBoxBFocusChanged true |> dispatch)
TextBox.onLostFocus (fun _ -> TextBoxBFocusChanged false |> dispatch)
]
|> View.withOutlet (fun tb -> textBoxB <- Some tb)
StackPanel.create [
StackPanel.orientation Orientation.Horizontal
StackPanel.margin 10
StackPanel.spacing 10
StackPanel.children [
Button.create [
Button.content "Focus A"
Button.background (
if state.textBoxAFocus then Brushes.Green else Brushes.Red
)
Button.onClick (fun _ ->
textBoxA
|> Option.iter (fun tb -> tb.Focus() |> ignore))
]
Button.create [
Button.content "Focus B"
Button.background (
if state.textBoxBFocus then Brushes.Green else Brushes.Red
)
Button.onClick (fun _ ->
textBoxB
|> Option.iter (fun tb -> tb.Focus() |> ignore))
]
]
]
]
]
Discussion