SaveFileDialog AddExtension не работает должным образом - PullRequest
2 голосов
/ 16 апреля 2019

У меня есть следующий код 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 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 Ответ

1 голос
/ 16 апреля 2019

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

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

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

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

Windows OS without

  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!

ПРИМЕЧАНИЯ

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...