Last active
February 19, 2025 04:36
-
-
Save mathias-brandewinder/991eab4598acae36f613af797a793302 to your computer and use it in GitHub Desktop.
Using Cmd.OfAsync in Avalonia FuncUI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See corresponding blog post: | |
// https://brandewinder.com/2025/02/19/async-commands-in-avalonia-funcui/ | |
module AsyncOperation = | |
open System | |
open Elmish | |
open Avalonia.Controls | |
open Avalonia.FuncUI.DSL | |
open Avalonia.FuncUI.Types | |
let respondToRequest (request: string) = | |
$"{DateTime.Now}: Request was {request}" | |
type State = { | |
Request: string | |
Response: string | |
} | |
type Msg = | |
| UpdateRequest of string | |
| SendRequest | |
let init (): State * Cmd<Msg> = | |
{ | |
Request = "" | |
Response = "" | |
}, | |
Cmd.none | |
let update (msg: Msg) (state: State): State * Cmd<Msg> = | |
match msg with | |
| UpdateRequest text -> | |
{ state with Request = text }, Cmd.none | |
| SendRequest -> | |
let response = respondToRequest state.Request | |
{ state with Response = response }, Cmd.none | |
let view (state: State) (dispatch: Msg -> unit): IView = | |
StackPanel.create [ | |
StackPanel.children [ | |
TextBox.create [ | |
TextBox.watermark "Type your request" | |
TextBox.text $"{state.Request}" | |
TextBox.onTextChanged (fun text -> | |
text | |
|> UpdateRequest | |
|> dispatch | |
) | |
] | |
Button.create [ | |
Button.content "Send Request" | |
Button.onClick (fun _ -> | |
SendRequest | |
|> dispatch | |
) | |
] | |
TextBlock.create [ | |
TextBlock.text state.Response | |
] | |
] | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See corresponding blog post: | |
// https://brandewinder.com/2025/02/19/async-commands-in-avalonia-funcui/ | |
module AsyncOperation = | |
open System | |
open Elmish | |
open Avalonia.Controls | |
open Avalonia.FuncUI.DSL | |
open Avalonia.FuncUI.Types | |
let respondToRequest (request: string) = | |
task { | |
// Create an artificial delay | |
do! Async.Sleep 1000 | |
return $"{DateTime.Now}: Request was {request}" | |
} | |
type State = { | |
Request: string | |
Response: string | |
} | |
type Msg = | |
| UpdateRequest of string | |
| SendRequest | |
| ReceivedResponse of string | |
let init (): State * Cmd<Msg> = | |
{ | |
Request = "" | |
Response = "" | |
}, | |
Cmd.none | |
let update (msg: Msg) (state: State): State * Cmd<Msg> = | |
match msg with | |
| UpdateRequest text -> | |
{ state with Request = text }, Cmd.none | |
| SendRequest -> | |
// for this to work you also need to use | |
// Program.runWithAvaloniaSyncDispatch () | |
// instead of Program.run | |
let deferredCmd = | |
Cmd.OfTask.perform | |
respondToRequest | |
state.Request | |
ReceivedResponse | |
state, deferredCmd | |
| ReceivedResponse response -> | |
{ state with Response = response }, Cmd.none | |
let view (state: State) (dispatch: Msg -> unit): IView = | |
StackPanel.create [ | |
StackPanel.children [ | |
TextBox.create [ | |
TextBox.watermark "Type your request" | |
TextBox.text $"{state.Request}" | |
TextBox.onTextChanged (fun text -> | |
text | |
|> UpdateRequest | |
|> dispatch | |
) | |
] | |
Button.create [ | |
Button.content "Send Request" | |
Button.onClick (fun _ -> | |
SendRequest | |
|> dispatch | |
) | |
] | |
TextBlock.create [ | |
TextBlock.text state.Response | |
] | |
] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment