У меня есть следующий код С#, который использует 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 name
и " Save 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
).
Есть ли способ изменить это?
Я не хочу делать это после закрытия диалогового окна, потому что тогда я должен снова проверить, существует ли файл и не слишком ли длинное имя файла.
Обновить:
Я также проверил это с платформой MONO, используя Ubuntu 18.04. В этом случае двойное расширение никогда не создается, например: test3.abc
с использованием MONO против test3.abc.txt
с использованием .NET Framework 4.5 (Windows 10).
Исходный код на моем Github (batressc)
Проще говоря, все расширения, кроме *.abc
являются допустимыми расширениями типов файлов в ОС Windows. Если для свойства AddExtension
задано AddExtension
true
, только если вы AddExtension
незарегистрированное расширение файла,.NET Framework автоматически AddExtension
имя файла со значением выбранного расширения файла в диалоговом окне сохранения файла.
В этом примере:
*.abc
(мы можем просмотреть расширения типа файла в HKEY_CLASSES_ROOT
используя regedit.exe
)
*.abc
в HKEY_CLASSES_ROOT
только создавая новый ключ с именем .abc
txt
не видна
Чтобы это исправить, мы можем создать метод расширения, чтобы он обязательно добавил выбранное расширение в диалог сохранения файла.
// It 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
:
ЗАМЕТКИ
В реализации FileDialog
Windows Forms (FileDialog.cs на GitHub) внутри кода, не указанного для поиска расширений файлов с использованием функций или методов ОС, методы GetExtension
и HasExtension
проверяют только шаблон .<extension>
в конце имени файла (Path.cs на GitHub). Может быть, проверка зарегистрированных расширений в ОС Windows является внутренней функциональностью Framework, и это не видно для разработчика... :(
FilterIndex
чтобы решить, должен ли я сохранять его как файлtxt
илиxml
а не как расширение свойстваFileName
.