SaveFileDialog AddExtension无法按预期工作

问题描述 投票:2回答:1

我有以下C#代码,它使用SaveFileDialog并将AddExtension属性设置为true

var dialog = new SaveFileDialog();
dialog.AddExtension = true;
dialog.DefaultExt = "txt";
dialog.Filter = "Text files (*.txt)|*.txt|XML files (*.xml)|*.xml";
dialog.OverwritePrompt = true;
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
    label1.Text = dialog.FileName;
}

我已经测试了对话框的File nameSave as type的以下组合。

File name       | Save as type   | label1.Text    | What I expect
----------------+----------------+----------------+----------------
test1           | *.txt          | test1.txt      | test1.txt
test2.txt       | *.txt          | test2.txt      | test2.txt
test3.abc       | *.txt          | test3.abc.txt  | test3.abc.txt
test4           | *.xml          | test4.xml      | test4.xml
test5.xml       | *.xml          | test5.xml      | test5.xml
test6.abc       | *.xml          | test6.abc.xml  | test6.abc.xml
----------------+----------------+----------------+----------------
test7.xml       | *.txt          | test7.xml      | test7.xml.txt
test8.bmp       | *.txt          | test8.bmp      | test8.bmp.txt
test9.bmp       | *.xml          | test9.bmp      | test9.bmp.xml     

对于上表的最后三行,我希望像未知的abc扩展一样进行双扩展。像Microsoft Word这样的应用程序就像那样(如果Save as type与用户在File name中给出的扩展名不匹配,它们总是添加双扩展名)。

有办法改变吗?

关闭对话框后我不想这样做,因为我要再次检查文件是否已经存在以及文件名是否太长。

更新:

我使用Ubuntu 18.04对MONO框架进行了测试。在这种情况下,永远不会创建双扩展,例如:使用.NET Framework 4.5(Windows 10)使用MONO vs test3.abctest3.abc.txt

c# .net mono file-extension savefiledialog
1个回答
1
投票

Source code on my Github (batressc)

简单来说,除了*.abc之外的所有扩展都是Windows操作系统中的有效文件类型扩展。在AddExtension中设置true属性时,仅当您放置未注册的文件扩展名时,.NET Framework才会自动在保存文件对话框中使用所选文件扩展名的值自动填充文件名。

在这个例子中:

  1. 在我的Windows 10操作系统中,我没有注册文件类型扩展名*.abc(我们可以使用HKEY_CLASSES_ROOTregedit.exe下查看文件类型扩展名)

Windows OS without "abc" file type extension

  1. 我用预期的结果测试“test3.abc”情况

Using third case Expected result

  1. 我在*.abc中注册HKEY_CLASSES_ROOT文件类型扩展名,只创建一个名为.abc的新密钥

Creating a new key

  1. 我重复第2点,现在txt部分不可见

Expected disgusting result

要解决此问题,我们可以创建一个扩展方法,确保在保存文件对话框中添加所选扩展名

// It's good practice create extensions methods in the same namespace of the class to extend
namespace System.Windows.Forms {
    public static class SaveFileDialogFileTypeExtension {
        // Retrieving only text of the file extensions
        private static List<string> GetFileExtensions(string filter) {
            List<string> extensions = new List<string>();
            var filtersRaw = filter.Split('|');
            for (int i = 0; i < filtersRaw.Length; i++) {
                if (i % 2 != 0) {
                    // Supporting multi doted extensions
                    extensions.Add(filtersRaw[i].Trim().Replace("*", "").Substring(1));
                }
            }
            return extensions;
        }

        // Getting filename with selected extension
        public static string FileNameForceExtension(this SaveFileDialog dialog) {
            string fileName = dialog.FileName;
            // Retrieving the current selected filter index
            List<string> extensions = GetFileExtensions(dialog.Filter);
            string selectedExtension = extensions[dialog.FilterIndex - 1];
            // Adding extension if need it
            if (!fileName.EndsWith($".{selectedExtension}")) {
                fileName = $"{fileName}.{selectedExtension}";
            }
            return fileName;
        }
    }
}

而不是使用FileName我们可以使用FileNameForceExtension。在我的情况下,我使用它形式:

textBoxFileName.Text = dialog.FileName + " | " + dialog.FileNameForceExtension();

这个结果使用test7.xml*.txt文件扩展名:

Fix it!

笔记

在未指定使用OS函数或方法查找文件扩展名的代码中的Windows窗体(FileDialog)的FileDialog.cs on GitHub的实现中,GetExtensionHasExtension方法仅在文件名的最后验证模式.<extension>Path.cs on GitHub)。也许在Windows操作系统中注册的扩展的验证是框架的内部功能,这对于开发人员来说是不可见的...... :(

© www.soinside.com 2019 - 2024. All rights reserved.