System.Windows.Forms.SaveFileDialog 不强制执行默认扩展名

Posted

技术标签:

【中文标题】System.Windows.Forms.SaveFileDialog 不强制执行默认扩展名【英文标题】:System.Windows.Forms.SaveFileDialog does not enforce default extension 【发布时间】:2009-10-21 06:23:32 【问题描述】:

我正在尝试使SaveFileDialogFileOpenDialog 强制对用户输入的文件名进行扩展。我尝试使用question 389070 中提出的示例,但它没有按预期工作:

var dialog = new SaveFileDialog())

dialog.AddExtension = true;
dialog.DefaultExt = "foo";
dialog.Filter = "Foo Document (*.foo)|*.foo";

if (dialog.ShowDialog() == DialogResult.OK)

    ...

如果用户在恰好存在文件test.xml 的文件夹中键入文本test,对话框将建议名称test.xml(而我真的只想在列表中看到*.foo)。更糟糕的是:如果用户选择test.xml,那么我确实会得到test.xml作为输出文件名。

如何确保SaveFileDialog 真的只允许用户选择*.foo 文件?或者至少,当用户点击Save时,它会替换/添加扩展?

建议的解决方案(实现FileOk 事件处理程序)仅完成部分工作,因为如果文件名的扩展名错误,我真的想禁用Save 按钮。

为了留在对话框中更新FileOk处理程序中文本框中显示的文件名,以反映具有正确扩展名的新文件名,请参阅following related question .

【问题讨论】:

我不确定,但您可以尝试将 multipleDottedExtensions 设置为 True,也许这确实会改变这种行为。 不,这根本没有改变;但感谢您的提示。 【参考方案1】:

您可以处理FileOk 事件,如果扩展名不正确则取消它

private saveFileDialog_FileOk(object sender, CancelEventArgs e)

    if (!saveFileDialog.FileName.EndsWith(".foo"))
    
        MessageBox.Show("Please select a filename with the '.foo' extension");
        e.Cancel = true;
    

【讨论】:

【参考方案2】:

AFAIK 没有可靠的方法来强制执行给定的文件扩展名。无论如何,验证正确的扩展名是一个很好的做法,一旦关闭对话框并通知用户如果扩展名不匹配,他选择了一个无效的文件。

【讨论】:

【参考方案3】:

我最接近的方法是使用 FileOk 事件。例如:

dialog.FileOk += openFileDialog1_FileOk;

private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)

  if(!dialog.FileName.EndsWith(".foo"))
   
     e.Cancel = true;
  

在 MSDN 上结帐 FileOK Event。

【讨论】:

【参考方案4】:

我遇到了同样的问题,我可以通过执行以下操作来控制显示的内容:

使用 OpenFileDialog,过滤器字符串中的第一项是默认值

openFileDialog1.Filter = "Program x Files (*.pxf)|*.pxf|txt files (*.txt)|*.txt";
openFileDialog1.ShowDialog();

使用 SaveFileDialog,过滤器中的第二项被用作默认值:

SaveFileDialog saveFileDialog1 = new SaveFileDialog();

saveFileDialog1.Filter = "txt files (*.txt)|*.txt|Program x Files (*.pxf)|*.pxf";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;

if (saveFileDialog1.ShowDialog() == DialogResult.OK)

    if (saveFileDialog1.FileName != null)
    
        // User has typed in a filename and did not click cancel
        saveFile = saveFileDialog1.FileName;
        MessageBox.Show(saveFile);
        saveCurrentState();

    
 

在将这两个过滤器与各自的文件对话框一起使用之后,终于出现了预期的结果。默认情况下,当用户选择保存按钮并显示 savefiledialog 时,所选文件类型是 savefiledialog 过滤器中定义的 Program X 文件类型。同样,openfiledialog 的选定文件类型是 openfileDialog 过滤器中定义的 Program X 文件类型的文件类型。

在这个线程中如上所述进行一些输入验证也是很好的。我只是想指出两个对话框之间的过滤器似乎不同,即使它们都继承了 filedialog 类。

【讨论】:

不,抱歉,您没有正确理解我的问题:使用 SaveFileDialog 的示例代码,没有什么能阻止用户输入 foo 并让 Windows 建议文件名 foo.xml(如果有)恰好是打开文件夹中具有该名称的 XML 文件。目前,您无法确保选择的文件名尊重所选的 *.pfx 扩展名(在您的情况下)。【参考方案5】:
    //this must be ran as administrator due to the change of a registry key, but it does work...

    private void doWork()
    
        const string lm = "HKEY_LOCAL_MACHINE";
        const string subkey = "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete";
        const string keyName = lm + subkey;

        int result = (int)Microsoft.Win32.Registry.GetValue(keyName, "AutoComplete In File Dialog", -1);

        MessageBox.Show(result.ToString());

        if(result.ToString() == "-1")
        
            //-1 means the key does not exist which means we must create one...
            Microsoft.Win32.Registry.SetValue(keyName, "AutoComplete In File Dialog", 0);
            OpenFileDialog ofd1 = new OpenFileDialog();
            ofd1.ShowDialog();
        
        if (result == 0)
        
            //The Registry value is already Created and set to '0' and we dont need to do anything
        
    

【讨论】:

关闭自动完成功能有点苛刻,不是吗?

以上是关于System.Windows.Forms.SaveFileDialog 不强制执行默认扩展名的主要内容,如果未能解决你的问题,请参考以下文章