龙腾猫跃 5 ماه پیش
والد
کامیت
03483d5f7a
3فایلهای تغییر یافته به همراه89 افزوده شده و 2 حذف شده
  1. 0 2
      Tests/Utils/DirectoryUtilsTest.cs
  2. 87 0
      Wpf/General/Dialogs.cs
  3. 2 0
      Wpf/MeloongCore.Wpf.csproj

+ 0 - 2
Tests/Utils/DirectoryUtilsTest.cs

@@ -1,5 +1,3 @@
-using TUnit.Assertions.Extensions;
-
 namespace MeloongCore.Tests;
 public class DirectoryUtilsTest : TestWithFolder {
 

+ 87 - 0
Wpf/General/Dialogs.cs

@@ -0,0 +1,87 @@
+using System.Windows.Forms;
+
+namespace MeloongCore.Wpf;
+
+public static class Dialogs {
+
+    /// <summary>
+    /// 弹出 “保存” 弹窗,返回用户选择的路径(若取消则返回 <c>null</c>)。
+    /// <para/> <paramref name="filter"/> 中的扩展名不加 <c>.</c>。
+    /// </summary>
+    public static string? SaveFile(string title, string defaultFileName = "", string? defaultDirectory = null, IEnumerable<(string Extension, string Display)>? filter = null) {
+        var filters = filter?.ToList();
+        using var dialog = new SaveFileDialog {
+            AddExtension = true,
+            AutoUpgradeEnabled = true,
+            Title = title,
+            FileName = defaultFileName
+        };
+        if (!string.IsNullOrEmpty(defaultDirectory) && Directory.Exists(defaultDirectory)) dialog.InitialDirectory = PathUtils.ToShortPath(defaultDirectory!);
+        if (filters != null) {
+            dialog.Filter = filters.Select(f => $"{f.Display}(*.{f.Extension})|*.{f.Extension}").Join("|");
+        }
+
+        Logger.Info($"保存弹窗:{dialog.Title}(FileName={dialog.FileName}, InitialDirectory={dialog.InitialDirectory}, Filter={dialog.Filter})");
+        dialog.ShowDialog();
+
+        var result = dialog.FileName;
+        Logger.Info($"保存弹窗返回:{result}");
+        if (!result.Contains('\\')) return null;
+        // AddExtension 可能失效,需要手动补全(#8214)
+        if (filters != null && !string.IsNullOrEmpty(result) && !filters.Any(f => result.EndsWithF("." + f.Extension))) {
+            result += "." + filters[dialog.FilterIndex - 1].Extension;
+            Logger.Warn($"选择文件的返回无扩展名,将会手动添加,修改后为:{result}");
+        }
+        return result;
+    }
+
+    /// <summary>
+    /// 弹出 “选择文件” 弹窗,返回用户选择的文件路径(若取消则返回空数组)。
+    /// <para/> <paramref name="filter"/> 中的扩展名不加 <c>.</c>。
+    /// </summary>
+    public static string[] SelectFile(string title, bool multiselect, string? defaultDirectory = null, IEnumerable<(string[] Extensions, string Display)>? filter = null) {
+        var filters = filter?.ToList();
+        using var dialog = new OpenFileDialog {
+            AddExtension = true,
+            AutoUpgradeEnabled = true,
+            CheckFileExists = true,
+            Multiselect = multiselect,
+            Title = title,
+            ValidateNames = true
+        };
+        if (!string.IsNullOrEmpty(defaultDirectory) && Directory.Exists(defaultDirectory)) dialog.InitialDirectory = PathUtils.ToShortPath(defaultDirectory!);
+        if (filters != null) {
+            dialog.Filter = filters.Select(f => {
+                var exts = string.Join(";", f.Extensions.Select(e => $"*.{e}"));
+                return $"{f.Display}({exts})|{exts}";
+            }).Join("|");
+        }
+
+        Logger.Info($"选择文件弹窗:{dialog.Title}(Multiselect={dialog.Multiselect}, InitialDirectory={dialog.InitialDirectory}, Filter={dialog.Filter})");
+        dialog.ShowDialog();
+
+        var results = multiselect ? dialog.FileNames : (string.IsNullOrEmpty(dialog.FileName) ? [] : [dialog.FileName]);
+        Logger.Info($"选择文件弹窗返回:{string.Join(",", results)}");
+        return results;
+    }
+
+    /// <summary>
+    /// 弹出选取文件夹对话框,返回用户选择的文件夹路径(以 \ 结尾),取消则返回空字符串。
+    /// </summary>
+    public static string SelectFolder(string title, string? defaultDirectory = null) {
+        var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog {
+            ShowNewFolderButton = true,
+            Description = title,
+            UseDescriptionForTitle = true
+        };
+        if (!string.IsNullOrEmpty(defaultDirectory) && Directory.Exists(defaultDirectory)) dialog.SelectedPath = defaultDirectory;
+
+        Logger.Info($"选择文件夹弹窗:{dialog.Description}(SelectedPath={dialog.SelectedPath})");
+        dialog.ShowDialog();
+
+        var result = string.IsNullOrEmpty(dialog.SelectedPath) ? "" : (dialog.SelectedPath!.EndsWithF('\\') ? dialog.SelectedPath! : dialog.SelectedPath! + '\\');
+        Logger.Info($"选择文件夹弹窗返回:{result}");
+        return result;
+    }
+
+}

+ 2 - 0
Wpf/MeloongCore.Wpf.csproj

@@ -15,6 +15,7 @@
 	</PropertyGroup>
 
 	<ItemGroup>
+		<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
 		<PackageReference Include="PolySharp" Version="1.15.0">
 			<PrivateAssets>all</PrivateAssets>
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -38,6 +39,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
+		<Reference Include="System.Windows.Forms" />
 		<Reference Include="PresentationCore" />
 		<Reference Include="PresentationFramework" />
 	</ItemGroup>