xamarin - 在 Fabulous (F#) UWP 应用中使用 Xamarin Essentials 文件选取器

标签 xamarin uwp f# xamarin.essentials

我正在测试使用 Fabulous 框架创建一个 UWP 应用程序,以编写功能性跨平台应用程序,并且我想在按下按钮时使用 FilePicker 并使用所选文件进行某些数据处理。

执行中 let fileResult = FilePicker.PickAsync() |> Async.AwaitTask打开文件选择器并返回 Async<FileResult>选择文件后(这意味着按钮和后续函数调用执行),但其后面的其余代码将在使用结果之前执行。如果我附加 |> Async.RunSynchronously它(如预期)会阻塞线程,并且在出现的窗口中无法选择任何文件,尽管返回值将是 FileResult。

在研究了如何完成此操作之后,我意识到应该在主线程上打开文件选择器,这导致我找到了以下形式的解决方案

let getFileResultAsync = 
                async {
                    let tcs = new TaskCompletionSource<FileResult>()
                    Device.BeginInvokeOnMainThread(fun () ->
                        async {
                            let! fileResult = FilePicker.PickAsync() |> Async.AwaitTask
                            tcs.SetResult(fileResult)
                        } 
                        |> Async.StartImmediate
                    )

                    return! tcs.Task |> Async.AwaitTask
                }

这将返回 Async<FileResult> ,但似乎从未访问过 Device.BeginInvokeOnMainThread block 。我将如何打开 FilePicker、选择一个文件,然后在这样的应用程序中处理该文件?

最佳答案

通过进一步研究测试示例以及有关更新和消息的 Fabulous 文档 https://fsprojects.github.io/Fabulous/Fabulous.XamarinForms/update.html,我找到了一种方法来完成我想要的操作.

基于创建新的 Fabulous 项目时生成的标准应用程序,只需在模型中包含给定的字符串,例如现在,文件路径(我称之为 FilePath),然后添加三个附加消息来键入 Msg,如下所示

type Msg =
...
| SelectFile
| PresentFile of FileResult 
| ErrorFileNotSelected

只要按下选择文件的按钮,就会发送第一个,第二个是在选择文件时发送的,第三个是在用户退出文件对话框而不选择文件的情况下发送的。

您需要一个异步选择文件的函数

let selectFileAsync = 
        async {
            let! result = FilePicker.PickAsync() |> Async.AwaitTask
            return result
        } 

还有一个 Fabulous.Cmd,它调用上述函数并在程序中进一步发送消息(可能是更好的解释方式)

let selectFileCmd = async {
            let! file = selectFileAsync

            match file with 
            | null ->  return Some(ErrorFileNotSelected)
            | _  -> return Some(PresentFile file)
        }

最后,将以下三个模式添加到更新中,其中在 SelectFile 下调用 selectFileCmd

let update msg model = 
...
| SelectFile ->
            {model with FilePath = "Selecting file"}, (Cmd.ofAsyncMsgOption selectFileCmd)
| PresentFile file -> 
            {model with FilePath = file.FullPath}, Cmd.none 
| ErrorFileNotSelected -> 
            {model with FilePath = "Error. Must select a file"}, Cmd.none

我不确定这是否被认为是一个好的方法,但它看起来至少比使用 let mutable 更好。

关于xamarin - 在 Fabulous (F#) UWP 应用中使用 Xamarin Essentials 文件选取器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65566343/

相关文章:

c# - 为 Windows 10 UWP 应用程序在桌面上设置窗口大小

algorithm - F# 算法中的意外 NullReferenceException

generics - 为什么 '!=' 的使用被认为是模棱两可的,而 '=' 的类似用法却不是?

f# - 使用 FsCheck 生成复杂对象时出现不一致的 IEnumerable ArgumentException

xamarin - 从 Xamarin 表单触发 native View 事件

c# - 为什么 xamarin 构建的应用程序在远程设备上崩溃

xamarin - 如何在 xamarin 的 toolbarItem 中添加图标?

c# - GetAllWithChildren() 性能问题

c# - UWP 后台已激活,找不到合适的方法来覆盖

sqlite - 使用Entity Framework Core和SQLite迁移数据库时,表已存在异常