[英]SaveFileDialog AddExtension doesn't work as expected
我有以下 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
)。
有沒有辦法改變它?
我不想在對話框關閉后執行此操作,因為那時我必須再次檢查文件是否已經存在以及文件名是否不太長。
更新:
我也使用 Ubuntu 18.04 使用 MONO 框架對其進行了測試。 在這種情況下,永遠不會創建雙重擴展名,例如:使用 MONO 的test3.abc
與使用 .NET Framework 4.5 (Windows 10) 的test3.abc.txt
。
簡單來說,除*.abc
之外的所有擴展名在 Windows 操作系統中都是有效的文件類型擴展名。 當您將AddExtension
屬性設置為true
時,僅當您放置未注冊的文件擴展名時,.NET Framework 會自動在保存文件對話框中自動完成具有所選文件擴展名值的文件名。
在這個例子中:
*.abc
(我們可以使用regedit.exe
查看HKEY_CLASSES_ROOT
下的文件類型擴展名)HKEY_CLASSES_ROOT
中注冊*.abc
文件類型擴展名,只創建一個名為.abc
的新密鑰txt
部分不可見為了解決這個問題,我們可以創建一個擴展方法,他確保在保存文件對話框中添加選定的擴展
// 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;
}
}
}
我們可以使用FileNameForceExtension
FileName
在我的例子中,我使用它的形式:
textBoxFileName.Text = dialog.FileName + " | " + dialog.FileNameForceExtension();
這是使用帶有*.txt
文件擴展名的test7.xml
的結果:
筆記
在 Windows 窗體( GitHub 上的 FileDialog.cs )的FileDialog
實現中,代碼中未指定使用 OS 函數或方法查找文件擴展名, GetExtension
和HasExtension
方法僅驗證模式.<extension>
最后的文件名( GitHub 上的 Path.cs )。 也許在 Windows 操作系統中驗證已注冊的擴展是框架的內部功能,這對開發人員來說是不可見的……:(
所以我知道現在回答有點晚了,因為你可能已經繼續前進了,但對於將來來這里尋找答案的其他人來說,就像我自己剛剛做的那樣,這就是答案:唯一的方法是制作你自己的 SaveFiledialog使用繼承 SaveFiledialog 的部分類控制或修改現有的。 Microsoft 將其標記為不可繼承。 許多基類都以某種方式受到保護,以防止人們修改它們。 這是一種可笑的不必要的痛苦,但事實就是如此。 即使您設法獲得了該類的副本,它也依賴於一堆其他受保護的東西。 你最好的選擇是完全自己制作或嘗試解析文件名並添加擴展名,如果它不存在,就像其他人所說的那樣。 是的,這很糟糕,因為一旦你添加了擴展名,文件名可能會變得太長,但你無能為力。 然而,Windows 10 上文件名的最大長度為 260 個字符,包括擴展名。 用戶很少會嘗試命名這么長的文件。 這不是你應該聽天由命的事情,但微軟讓我們別無選擇。 一種選擇是如果用戶不使用消息框然后再次顯示對話框,則只要求用戶添加擴展名。 如果至少有一個屬性可以將對話框的最大文件名長度設置為自定義長度(這在更多情況下會有用,而不僅僅是我可能添加的。@microsoft),那么這將允許您考慮可能需要添加擴展名,但甚至沒有這樣做的選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.