Vixen
02b45cc4
csharp
public sealed class WindowsDialogs

The Windows file pickers, through the shell's IFileDialog.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

COM by vtable rather than by interface declaration. Five interfaces are needed and nine methods of them; a ComWrappers generator or a set of [GeneratedComInterface] declarations would be more code, not less, and would put a marshalling layer between us and an ABI that is four function-pointer calls deep. What is here is the calls, with the vtable slot beside each one, which is the form in which a mistake is visible.

Not WinRT, and therefore not net10.0-windows. The plan (docs/plan/10) named WinRT's FileOpenPicker; that needs a Windows-versioned target framework, which would spread from here to every consumer that references it — the app head, the editor, the samples — and turn a portable build graph into a multi-targeted one. It would also take this assembly out of nuke CheckApi, which only covers net10.0. The WinRT picker for a desktop application is a wrapper over IFileDialog, so the cost buys nothing the user can see.

Each dialog gets its own STA thread. A modal shell dialog runs its own message loop until the user is finished, which is as long as they take. Running it on the frame thread would stop the frame loop for that whole time and Windows would draw the ghosted "not responding" chrome over a window that is fine. The dialog is still modal to the application — it is given the owner window, which Windows disables for the duration — and one is shown at a time, which is what the gate is for.

Cancellation is honoured before the dialog opens and not after. Closing an open IFileDialog means calling Close on the apartment that owns it, from outside its message loop, which is a deadlock waiting for a slow network place to enumerate. INativeDialogs says a token dismisses a dialog "where the platform allows it"; this is one of the places it does not.

Methods (7)

  • public WindowsDialogs(INativeDialogs fallback)

    The Windows file pickers, through the shell's IFileDialog.

  • public ValueTask<string?> OpenFileAsync(FileDialogOptions options, IWindow? owner = null, CancellationToken cancellationToken = default(CancellationToken))

    Asks the user to pick one existing file.

  • public ValueTask<IReadOnlyList<string>> OpenFilesAsync(FileDialogOptions options, IWindow? owner = null, CancellationToken cancellationToken = default(CancellationToken))

    Asks the user to pick one or more existing files.

  • public ValueTask<string?> SaveFileAsync(FileDialogOptions options, IWindow? owner = null, CancellationToken cancellationToken = default(CancellationToken))

    Asks the user where to save.

  • public ValueTask<string?> OpenFolderAsync(FileDialogOptions options, IWindow? owner = null, CancellationToken cancellationToken = default(CancellationToken))

    Asks the user to pick a folder.

  • public ValueTask<MessageBoxResult> ShowMessageAsync(MessageBoxOptions options, IWindow? owner = null, CancellationToken cancellationToken = default(CancellationToken))

    Shows the message box the portable implementation shows.

  • public void Dispose()

    Releases the gate that keeps one dialog open at a time.

Used by (1)

  • WindowsPlatformSupplementVixen.Platform.Windows