Reputation: 53
I've got a working FuncUI app, but adding a file picker to get some text from the file system is proving tricky. I've stripped my app down to the following app based on a modified version of the counter app on the Avalonia FuncUI home page. It runs fine, but hangs at line 34 in the Async.RunSynchronously after you press the "Load File" button:
namespace CounterApp
open Avalonia
open Avalonia.Controls.ApplicationLifetimes
open Avalonia.Themes.Fluent
open Avalonia.FuncUI.Hosts
open Avalonia.Controls
open Avalonia.FuncUI
open Avalonia.FuncUI.DSL
open Avalonia.Layout
open Avalonia.Platform.Storage
open System.IO
module Main =
let view () =
Component(fun ctx ->
let state = ctx.useState 0
let top = TopLevel.GetTopLevel ctx.control
let useFiles() =
async {
let options = FilePickerOpenOptions(Title = "Open Text File", AllowMultiple = false)
let! result = top.StorageProvider.OpenFilePickerAsync(options) |> Async.AwaitTask
return result
}
let callback _ =
useFiles()
|> Async.RunSynchronously |> ignore
DockPanel.create [
DockPanel.children [
Button.create [
Button.dock Dock.Bottom
Button.onClick callback
Button.content "Load file"
Button.horizontalAlignment HorizontalAlignment.Stretch
Button.horizontalContentAlignment HorizontalAlignment.Center
]
]
]
)
type MainWindow() =
inherit HostWindow()
do
base.Title <- "Counter Example"
base.Content <- Main.view ()
type App() =
inherit Application()
override this.Initialize() =
this.Styles.Add (FluentTheme())
this.RequestedThemeVariant <- Styling.ThemeVariant.Dark
override this.OnFrameworkInitializationCompleted() =
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime ->
desktopLifetime.MainWindow <- MainWindow()
| _ -> ()
module Program =
[<EntryPoint>]
let main(args: string[]) =
AppBuilder
.Configure<App>()
.UsePlatformDetect()
.UseSkia()
.StartWithClassicDesktopLifetime(args)
This is my best approximation at what might be a way to go, but I am now stuck. Any ideas on what would make this working code?
Upvotes: 0
Views: 281
Reputation: 53
While looking to see if anyone had answered my question, Google reported an Avalonia FuncUI link on github to me, which in turn, led me to reading an article on Elmish, the wider context for my app.
Turns out all I needed to proceed was to make the callback a void function, and to start the task immediately:
let useFiles() =
async {
let options = FilePickerOpenOptions(Title = "Open Text File",
AllowMultiple = false)
let! result =
top.StorageProvider.OpenFilePickerAsync(options)
|> Async.AwaitTask
System.Console.WriteLine "result now available"
}
let callback _ =
useFiles()
|> Async.StartImmediate
This successfully calls the file picker, thus solving my stated problem. I can now continue and make use of the file picker's choice returned in result
.
Upvotes: 1