Primary APIs:
TopLevel.GetTopLevel(...)TopLevel.StorageProviderIStorageProviderIStorageFile, IStorageFolder, IStorageItemFilePickerOpenOptions, FilePickerSaveOptions, FolderPickerOpenOptionsFilePickerFileTypeStorageProviderExtensions.TryGetFileFromPathAsync(...)StorageProviderExtensions.TryGetFolderFromPathAsync(...)StorageProviderExtensions.TryGetLocalPath(...)WellKnownFolderManagedFileDialogExtensionsImportant members:
IStorageProvider.CanOpen, CanSave, CanPickFolderOpenFilePickerAsync(...)SaveFilePickerAsync(...), SaveFilePickerWithResultAsync(...)OpenFolderPickerAsync(...)TryGetFileFromPathAsync(...), TryGetFolderFromPathAsync(...)TryGetWellKnownFolderAsync(...)IStorageFile.OpenReadAsync(), OpenWriteAsync()IStorageItem.SaveBookmarkAsync(), DeleteAsync(), MoveAsync(...)ShowManagedAsync(...)Reference source files:
src/Avalonia.Controls/TopLevel.cssrc/Avalonia.Base/Platform/Storage/IStorageProvider.cssrc/Avalonia.Base/Platform/Storage/IStorageItem.cssrc/Avalonia.Base/Platform/Storage/IStorageFile.cssrc/Avalonia.Base/Platform/Storage/IStorageFolder.cssrc/Avalonia.Base/Platform/Storage/FilePickerOpenOptions.cssrc/Avalonia.Base/Platform/Storage/FilePickerSaveOptions.cssrc/Avalonia.Base/Platform/Storage/StorageProviderExtensions.cssrc/Avalonia.Base/Platform/Storage/WellKnownFolder.cssrc/Avalonia.Dialogs/ManagedFileDialogExtensions.csProvider model:
TopLevel from a visual at interaction time.TopLevel.StorageProvider.Notes:
file: vs content: or isolated browser paths).using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
public static class StorageWorkflows
{
public static async Task<IReadOnlyList<IStorageFile>> OpenJsonFilesAsync(Control anchor)
{
TopLevel? top = TopLevel.GetTopLevel(anchor);
if (top is null || !top.StorageProvider.CanOpen)
return Array.Empty<IStorageFile>();
IStorageFolder? start = await top.StorageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents);
FilePickerFileType json = new("JSON")
{
Patterns = new[] { "*.json" },
MimeTypes = new[] { "application/json" }
};
return await top.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = "Open JSON",
AllowMultiple = true,
SuggestedStartLocation = start,
FileTypeFilter = new[] { json },
SuggestedFileType = json
});
}
public static async Task<IStorageFile?> SaveTextFileAsync(Control anchor, string suggestedName)
{
TopLevel? top = TopLevel.GetTopLevel(anchor);
if (top is null || !top.StorageProvider.CanSave)
return null;
FilePickerFileType text = new("Text")
{
Patterns = new[] { "*.txt" },
MimeTypes = new[] { "text/plain" }
};
return await top.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
{
Title = "Save As",
SuggestedFileName = suggestedName,
DefaultExtension = "txt",
FileTypeChoices = new[] { text },
SuggestedFileType = text,
ShowOverwritePrompt = true
});
}
}
When Avalonia.Dialogs managed dialogs are enabled, ManagedFileDialogExtensions adds:
ShowManagedAsync(this OpenFileDialog dialog, Window parent, ManagedFileDialogOptions? options = null)ShowManagedAsync<TWindow>(this OpenFileDialog dialog, Window parent, ManagedFileDialogOptions? options = null)Use these as compatibility shims when you need managed dialog behavior across platforms with inconsistent native dialog support.
Bookmark strategy:
IStorageItem.CanBookmark is true, persist bookmark IDs instead of raw paths.OpenFileBookmarkAsync(...) / OpenFolderBookmarkAsync(...).Path strategy:
TryGetLocalPath() only when truly needed.IStorageFile.OpenReadAsync() and OpenWriteAsync() over path-based IO.Default mode:
XAML-first complete example:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.ViewModels"
x:DataType="vm:StorageToolsViewModel">
<StackPanel Margin="12" Spacing="8">
<Button Content="Open JSON" Command="{CompiledBinding OpenJsonCommand}" />
<Button Content="Save Report" Command="{CompiledBinding SaveReportCommand}" />
<TextBlock Text="{CompiledBinding LastPath}" />
</StackPanel>
</UserControl>
Code-only alternative (on request):
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
public static class CodeOnlyStorageSample
{
public static async Task SaveSampleAsync(Control anchor)
{
IStorageFile? file = await StorageWorkflows.SaveTextFileAsync(anchor, "report.txt");
if (file is null)
return;
await using Stream stream = await file.OpenWriteAsync();
await using StreamWriter writer = new(stream, Encoding.UTF8, leaveOpen: false);
await writer.WriteLineAsync("Generated by Avalonia storage workflow.");
}
}
IStorageItem instances once done.Path may be URI-like and not a local file path.CanPickFolder false for current runtime/backend.