Dialogs.cs 4.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using Microsoft.Win32;
  2. namespace MeloongCore.Wpf;
  3. public static class Dialogs {
  4. /// <summary>
  5. /// 弹出 “保存” 弹窗,返回用户指定的路径,若取消则返回 <c>null</c>。
  6. /// <para/> <paramref name="filter"/> 中的扩展名不加 <c>.</c>。
  7. /// </summary>
  8. public static string? SaveFile(string title, string defaultFileName = "", string? defaultDirectory = null, IEnumerable<(string Extension, string Display)>? filter = null) {
  9. var filters = filter?.ToList();
  10. var dialog = new SaveFileDialog {
  11. AddExtension = true,
  12. Title = title,
  13. FileName = defaultFileName
  14. };
  15. if (!string.IsNullOrEmpty(defaultDirectory) && DirectoryUtils.Exists(defaultDirectory!)) dialog.InitialDirectory = PathUtils.ToShortPath(defaultDirectory!);
  16. if (filters is not null) {
  17. dialog.Filter = filters.Select(f => $"{f.Display}(*.{f.Extension})|*.{f.Extension}").Join("|");
  18. }
  19. Logger.Info($"保存弹窗:{dialog.Title}(FileName={dialog.FileName}, InitialDirectory={dialog.InitialDirectory}, Filter={dialog.Filter})");
  20. if (dialog.ShowDialog() != true) return null;
  21. var result = dialog.FileName;
  22. Logger.Info($"保存弹窗返回:{result}");
  23. if (!result.Contains(Path.DirectorySeparatorChar)) return null;
  24. // AddExtension 可能失效,需要手动补全(#8214)
  25. if (filters != null && !string.IsNullOrEmpty(result) && !filters.Any(f => result.EndsWithF("." + f.Extension))) {
  26. result += "." + filters[dialog.FilterIndex - 1].Extension;
  27. Logger.Warn($"选择文件的返回无扩展名,将会手动添加,修改后为:{result}");
  28. }
  29. return result;
  30. }
  31. /// <summary>
  32. /// 弹出 “选择文件” 弹窗,返回用户选择的文件路径,若取消则返回空数组。
  33. /// <para/> 若使用扩展名 <paramref name="filter"/>,则扩展名不加 <c>.</c>。
  34. /// </summary>
  35. public static List<string> SelectFile(string title, bool multiselect, string? defaultDirectory = null, OneOf<IEnumerable<(string[] Extensions, string Display)>, string>? filter = null) {
  36. var dialog = new OpenFileDialog {
  37. AddExtension = true,
  38. CheckFileExists = true,
  39. Multiselect = multiselect,
  40. Title = title,
  41. ValidateNames = true
  42. };
  43. if (!string.IsNullOrEmpty(defaultDirectory) && DirectoryUtils.Exists(defaultDirectory!)) dialog.InitialDirectory = PathUtils.ToShortPath(defaultDirectory!);
  44. if (filter is not null) {
  45. if (filter.Value.Is<string>()) {
  46. dialog.Filter = filter.Value.As<string>();
  47. } else {
  48. dialog.Filter = filter.Value.As<IEnumerable<(string[] Extensions, string Display)>>().Select(f => {
  49. var exts = string.Join(";", f.Extensions.Select(e => $"*.{e}"));
  50. return $"{f.Display}({exts})|{exts}";
  51. }).Join("|");
  52. }
  53. }
  54. Logger.Info($"选择文件弹窗:{dialog.Title}(Multiselect={dialog.Multiselect}, InitialDirectory={dialog.InitialDirectory}, Filter={dialog.Filter})");
  55. if (dialog.ShowDialog() != true) return [];
  56. var results = dialog.FileNames.Where(f => f.Contains(Path.DirectorySeparatorChar)).ToList();
  57. Logger.Info($"选择文件弹窗返回:{results.Join(",")}");
  58. return results;
  59. }
  60. /// <summary>
  61. /// 弹出 “选择文件夹” 弹窗,返回用户选择的文件夹路径(以分隔符结尾),若取消则返回空数组。
  62. /// </summary>
  63. public static List<string> SelectFolder(string title, bool multiselect, string? defaultDirectory = null) {
  64. var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog {
  65. ShowNewFolderButton = true,
  66. Description = title,
  67. Multiselect = multiselect,
  68. UseDescriptionForTitle = true
  69. };
  70. if (!string.IsNullOrEmpty(defaultDirectory) && DirectoryUtils.Exists(defaultDirectory!)) dialog.SelectedPath = defaultDirectory;
  71. Logger.Info($"选择文件夹弹窗:{dialog.Description}(Multiselect={dialog.Multiselect}, SelectedPath={dialog.SelectedPath})");
  72. if (dialog.ShowDialog() != true) return [];
  73. var results = dialog.SelectedPaths.Where(f => f.Contains(Path.DirectorySeparatorChar)).Select(PathUtils.AddSlashSuffix).ToList();
  74. Logger.Info($"选择文件夹弹窗返回:{results.Join(",")}");
  75. return results;
  76. }
  77. }