SaveFileDialog AddExtension не работает должным образом

2

У меня есть следующий код С#, который использует 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).

  • 1
    From FileDialog.AddExtension Property : «Получает или задает значение, указывающее, будет ли диалоговое окно автоматически добавлять расширение к имени файла, если пользователь пропускает расширение ».
  • 0
    Я использую свойство FilterIndex чтобы решить, должен ли я сохранять его как файл txt или xml а не как расширение свойства FileName .
Показать ещё 3 комментария
Теги:
mono
file-extension
savefiledialog

1 ответ

1

Исходный код на моем Github (batressc)

Проще говоря, все расширения, кроме *.abc являются допустимыми расширениями типов файлов в ОС Windows. Если для свойства AddExtension задано AddExtension true, только если вы AddExtension незарегистрированное расширение файла,.NET Framework автоматически AddExtension имя файла со значением выбранного расширения файла в диалоговом окне сохранения файла.

В этом примере:

  1. В моей ОС Windows 10 я не зарегистрировал расширение типа файла *.abc (мы можем просмотреть расширения типа файла в HKEY_CLASSES_ROOT используя regedit.exe)

Изображение 174551

  1. Я тестирую случай "test3.abc" с ожидаемым результатом

Изображение 174551 Изображение 174551

  1. Я регистрирую расширение типа файла *.abc в HKEY_CLASSES_ROOT только создавая новый ключ с именем .abc

Изображение 174551

  1. Я повторяю пункт 2, и теперь часть txt не видна

Изображение 174551

Чтобы это исправить, мы можем создать метод расширения, чтобы он обязательно добавил выбранное расширение в диалог сохранения файла.

// 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:

Изображение 174551

ЗАМЕТКИ

В реализации FileDialog Windows Forms (FileDialog.cs на GitHub) внутри кода, не указанного для поиска расширений файлов с использованием функций или методов ОС, методы GetExtension и HasExtension проверяют только шаблон .<extension> в конце имени файла (Path.cs на GitHub). Может быть, проверка зарегистрированных расширений в ОС Windows является внутренней функциональностью Framework, и это не видно для разработчика... :(

  • 0
    Это решение не удовлетворяет следующему требованию: я не хочу делать это после закрытия диалогового окна, потому что тогда я должен еще раз проверить, существует ли файл и не слишком ли длинное имя файла.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню