diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 903c849834..8358fb3cd4 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -1,6 +1,6 @@
- netstandard2.0
+ netstandard2.0;net6.0
true
enable
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index d8dc3bad2d..b6ce59f15b 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -69,6 +69,9 @@
+
+
+
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index d675324d9f..47d11738bc 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -24,11 +24,6 @@ namespace ControlCatalog
{
IList tabItems = ((IList)sideBar.Items);
tabItems.Add(new TabItem()
- {
- Header = "Dialogs",
- Content = new DialogsPage()
- });
- tabItems.Add(new TabItem()
{
Header = "Screens",
Content = new ScreenPage()
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index 8a835867b3..cc23ef796a 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -1,29 +1,57 @@
-
-
- Use filters
-
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use filters
+
+
+ Force managed dialog
+ Open multiple
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index efa30c2741..f7b6db1255 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -1,13 +1,21 @@
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Threading.Tasks;
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Dialogs;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
-#pragma warning disable 4014
+using Avalonia.Platform.Storage;
+using Avalonia.Platform.Storage.FileIO;
+
+#pragma warning disable CS0618 // Type or member is obsolete
+#nullable enable
+
namespace ControlCatalog.Pages
{
public class DialogsPage : UserControl
@@ -18,13 +26,16 @@ namespace ControlCatalog.Pages
var results = this.Get("PickerLastResults");
var resultsVisible = this.Get("PickerLastResultsVisible");
+ var bookmarkContainer = this.Get("BookmarkContainer");
+ var openedFileContent = this.Get("OpenedFileContent");
+ var openMultiple = this.Get("OpenMultiple");
- string? lastSelectedDirectory = null;
+ IStorageFolder? lastSelectedDirectory = null;
- List? GetFilters()
+ List GetFilters()
{
if (this.Get("UseFilters").IsChecked != true)
- return null;
+ return new List();
return new List
{
new FileDialogFilter
@@ -39,12 +50,23 @@ namespace ControlCatalog.Pages
};
}
+ List? GetFileTypes()
+ {
+ if (this.Get("UseFilters").IsChecked != true)
+ return null;
+ return new List
+ {
+ FilePickerFileTypes.All,
+ FilePickerFileTypes.TextPlain
+ };
+ }
+
this.Get
diff --git a/src/Avalonia.Dialogs/ManagedFileChooserFilterViewModel.cs b/src/Avalonia.Dialogs/ManagedFileChooserFilterViewModel.cs
index a0cb664b40..062daef225 100644
--- a/src/Avalonia.Dialogs/ManagedFileChooserFilterViewModel.cs
+++ b/src/Avalonia.Dialogs/ManagedFileChooserFilterViewModel.cs
@@ -1,48 +1,31 @@
-using System;
-using System.Collections.Generic;
using System.Linq;
-using Avalonia.Controls;
+using System.Text.RegularExpressions;
+using Avalonia.Platform.Storage;
namespace Avalonia.Dialogs
{
internal class ManagedFileChooserFilterViewModel : InternalViewModelBase
{
- private readonly string[] _extensions;
+ private readonly Regex[] _patterns;
public string Name { get; }
- public ManagedFileChooserFilterViewModel(FileDialogFilter filter)
+ public ManagedFileChooserFilterViewModel(FilePickerFileType filter)
{
Name = filter.Name;
- if (filter.Extensions.Contains("*"))
+ if (filter.Patterns?.Contains("*.*") == true)
{
return;
}
- _extensions = filter.Extensions?.Select(e => "." + e.ToLowerInvariant()).ToArray();
- }
-
- public ManagedFileChooserFilterViewModel()
- {
- Name = "All files";
+ _patterns = filter.Patterns?
+ .Select(e => new Regex(Regex.Escape(e).Replace(@"\*", ".*").Replace(@"\?", "."), RegexOptions.Singleline | RegexOptions.IgnoreCase))
+ .ToArray();
}
public bool Match(string filename)
{
- if (_extensions == null)
- {
- return true;
- }
-
- foreach (var ext in _extensions)
- {
- if (filename.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
+ return _patterns == null || _patterns.Any(ext => ext.IsMatch(filename));
}
public override string ToString() => Name;
diff --git a/src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs b/src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs
index 405a248caf..986f43b1a1 100644
--- a/src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs
+++ b/src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs
@@ -8,6 +8,7 @@ using System.Runtime.InteropServices;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
+using Avalonia.Platform.Storage;
using Avalonia.Threading;
namespace Avalonia.Dialogs
@@ -106,7 +107,7 @@ namespace Avalonia.Dialogs
QuickLinks.AddRange(quickSources.GetAllItems().Select(i => new ManagedFileChooserItemViewModel(i)));
}
- public ManagedFileChooserViewModel(FileSystemDialog dialog, ManagedFileDialogOptions options)
+ public ManagedFileChooserViewModel(ManagedFileDialogOptions options)
{
_options = options;
_disposables = new CompositeDisposable();
@@ -131,50 +132,63 @@ namespace Avalonia.Dialogs
CancelRequested += delegate { _disposables?.Dispose(); };
RefreshQuickLinks(quickSources);
+
+ SelectedItems.CollectionChanged += OnSelectionChangedAsync;
+ }
- Title = dialog.Title ?? (
- dialog is OpenFileDialog ? "Open file"
- : dialog is SaveFileDialog ? "Save file"
- : dialog is OpenFolderDialog ? "Select directory"
- : throw new ArgumentException(nameof(dialog)));
-
- var directory = dialog.Directory;
-
- if (directory == null || !Directory.Exists(directory))
+ public ManagedFileChooserViewModel(FilePickerOpenOptions filePickerOpen, ManagedFileDialogOptions options)
+ : this(options)
+ {
+ Title = filePickerOpen.Title ?? "Open file";
+
+ if (filePickerOpen.FileTypeFilter?.Count > 0)
{
- directory = Directory.GetCurrentDirectory();
+ Filters.AddRange(filePickerOpen.FileTypeFilter.Select(f => new ManagedFileChooserFilterViewModel(f)));
+ _selectedFilter = Filters[0];
+ ShowFilters = true;
}
- if (dialog is FileDialog fd)
+ if (filePickerOpen.AllowMultiple)
{
- if (fd.Filters?.Count > 0)
- {
- Filters.AddRange(fd.Filters.Select(f => new ManagedFileChooserFilterViewModel(f)));
- _selectedFilter = Filters[0];
- ShowFilters = true;
- }
+ SelectionMode = SelectionMode.Multiple;
+ }
- if (dialog is OpenFileDialog ofd)
- {
- if (ofd.AllowMultiple)
- {
- SelectionMode = SelectionMode.Multiple;
- }
- }
+ Navigate(filePickerOpen.SuggestedStartLocation);
+ }
+
+ public ManagedFileChooserViewModel(FilePickerSaveOptions filePickerSave, ManagedFileDialogOptions options)
+ : this(options)
+ {
+ Title = filePickerSave.Title ?? "Save file";
+
+ if (filePickerSave.FileTypeChoices?.Count > 0)
+ {
+ Filters.AddRange(filePickerSave.FileTypeChoices.Select(f => new ManagedFileChooserFilterViewModel(f)));
+ _selectedFilter = Filters[0];
+ ShowFilters = true;
}
+
+ _savingFile = true;
+ _defaultExtension = filePickerSave.DefaultExtension;
+ _overwritePrompt = filePickerSave.ShowOverwritePrompt ?? true;
+ FileName = filePickerSave.SuggestedFileName;
+
+ Navigate(filePickerSave.SuggestedStartLocation, FileName);
+ }
+
+ public ManagedFileChooserViewModel(FolderPickerOpenOptions folderPickerOpen, ManagedFileDialogOptions options)
+ : this(options)
+ {
+ Title = folderPickerOpen.Title ?? "Select directory";
- _selectingDirectory = dialog is OpenFolderDialog;
+ _selectingDirectory = true;
- if (dialog is SaveFileDialog sfd)
+ if (folderPickerOpen.AllowMultiple)
{
- _savingFile = true;
- _defaultExtension = sfd.DefaultExtension;
- _overwritePrompt = sfd.ShowOverwritePrompt ?? true;
- FileName = sfd.InitialFileName;
+ SelectionMode = SelectionMode.Multiple;
}
- Navigate(directory, (dialog as FileDialog)?.InitialFileName);
- SelectedItems.CollectionChanged += OnSelectionChangedAsync;
+ Navigate(folderPickerOpen.SuggestedStartLocation);
}
public void EnterPressed()
@@ -247,6 +261,23 @@ namespace Avalonia.Dialogs
public void Refresh() => Navigate(Location);
+ public void Navigate(IStorageFolder path, string initialSelectionName = null)
+ {
+ string fullDirectoryPath;
+
+ if (path?.TryGetUri(out var fullDirectoryUri) == true
+ && fullDirectoryUri.IsAbsoluteUri)
+ {
+ fullDirectoryPath = fullDirectoryUri.LocalPath;
+ }
+ else
+ {
+ fullDirectoryPath = Directory.GetCurrentDirectory();
+ }
+
+ Navigate(fullDirectoryPath, initialSelectionName);
+ }
+
public void Navigate(string path, string initialSelectionName = null)
{
if (!Directory.Exists(path))
diff --git a/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs b/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
index e4025453c4..fe2dd99100 100644
--- a/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
+++ b/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
@@ -1,125 +1,26 @@
-using System.IO;
+#nullable enable
+
+using System;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
+using Avalonia.Platform.Storage;
namespace Avalonia.Dialogs
{
public static class ManagedFileDialogExtensions
{
- internal class ManagedSystemDialogImpl : ISystemDialogImpl where T : Window, new()
+ internal class ManagedStorageProviderFactory : IStorageProviderFactory where T : Window, new()
{
- async Task Show(SystemDialog d, Window parent, ManagedFileDialogOptions options = null)
+ public IStorageProvider CreateProvider(TopLevel topLevel)
{
- var model = new ManagedFileChooserViewModel((FileSystemDialog)d,
- options ?? new ManagedFileDialogOptions());
-
- var dialog = new T
- {
- Content = new ManagedFileChooser(),
- Title = d.Title,
- DataContext = model
- };
-
- dialog.Closed += delegate { model.Cancel(); };
-
- string[] result = null;
-
- model.CompleteRequested += items =>
- {
- result = items;
- dialog.Close();
- };
-
- model.OverwritePrompt += async (filename) =>
+ if (topLevel is Window window)
{
- Window overwritePromptDialog = new Window()
- {
- Title = "Confirm Save As",
- SizeToContent = SizeToContent.WidthAndHeight,
- WindowStartupLocation = WindowStartupLocation.CenterOwner,
- Padding = new Thickness(10),
- MinWidth = 270
- };
-
- string name = Path.GetFileName(filename);
-
- var panel = new DockPanel()
- {
- HorizontalAlignment = Layout.HorizontalAlignment.Stretch
- };
-
- var label = new Label()
- {
- Content = $"{name} already exists.\nDo you want to replace it?"
- };
-
- panel.Children.Add(label);
- DockPanel.SetDock(label, Dock.Top);
-
- var buttonPanel = new StackPanel()
- {
- HorizontalAlignment = Layout.HorizontalAlignment.Right,
- Orientation = Layout.Orientation.Horizontal,
- Spacing = 10
- };
-
- var button = new Button()
- {
- Content = "Yes",
- HorizontalAlignment = Layout.HorizontalAlignment.Right
- };
-
- button.Click += (sender, args) =>
- {
- result = new string[1] { filename };
- overwritePromptDialog.Close();
- dialog.Close();
- };
-
- buttonPanel.Children.Add(button);
-
- button = new Button()
- {
- Content = "No",
- HorizontalAlignment = Layout.HorizontalAlignment.Right
- };
-
- button.Click += (sender, args) =>
- {
- overwritePromptDialog.Close();
- };
-
- buttonPanel.Children.Add(button);
-
- panel.Children.Add(buttonPanel);
- DockPanel.SetDock(buttonPanel, Dock.Bottom);
-
- overwritePromptDialog.Content = panel;
-
- await overwritePromptDialog.ShowDialog(dialog);
- };
-
- model.CancelRequested += dialog.Close;
-
- await dialog.ShowDialog