设置SaveFileDialog的初始目录?

时间:2009-07-24 00:33:47

标签: c# .net wpf winapi

我想要一个具有以下行为的SaveFileDialog:

  • 第一次打开它时,会转到“我的文档”。

  • 之后,它会转到最后选择的文件夹。 什么是实现这一目标的最佳方式?

如果我没有设置InitialDirectory,它会转到exe的目录 - 这不是我想要的。它记住了最后选择的目录 - 即使在执行之间。

如果我设置了InitialDirectory,它就不记得最后选择的目录了。当然,我可以在注册表中保存最后选择的目录:(但我正在寻找更好的解决方案。

      SaveFileDialog dialog = new SaveFileDialog();
      //??? dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
      dialog.ShowDialog();

有什么建议吗?

15 个答案:

答案 0 :(得分:32)

您需要将RestoreDirectory设置为true以及InitialDirectory属性。

答案 1 :(得分:15)

我不知道为什么会这样,但我终于能够让它为我工作了。

我发现如果我给出完整路径,它就行不通,但是如果我把完整路径放在 Path.GetFullPath()中,那么它就可以了。查看之前和之后的值表明它们是相同的,但如果没有它,它将始终不起作用,并使用它。

//does not work
OpenFileDialog dlgOpen = new OpenFileDialog();
string initPath = Path.GetTempPath() + @"\FQUL";
dlgOpen.InitialDirectory = initPath;
dlgOpen.RestoreDirectory = true;

//works
OpenFileDialog dlgOpen = new OpenFileDialog();
string initPath = Path.GetTempPath() + @"\FQUL";
dlgOpen.InitialDirectory = Path.GetFullPath(initPath);
dlgOpen.RestoreDirectory = true;

答案 2 :(得分:4)

确保在设置Initial directory属性之前检查目录路径是否存在。如果目录不存在,请创建该目录。即

if (!Directory.Exists(FooDirectory))
{
     Directory.CreateDirectory(FooDirectory);
}

答案 3 :(得分:3)

我也尝试过在不同的地方找到不同的“解决方案”,但是一旦注册表中有MRU列表条目,它们似乎都没有工作:/但这是我自己的简单解决方法......

不是设置对话框的InitialDirectory属性,而是将FileName属性设置为您的路径,但与选定的Filter结合使用,例如:

dialog.FileName = Path.Combine(myPath, "*.*");

答案 4 :(得分:1)

所提供的解决方案都没有让我伤心。

除OP规范外,我希望程序能够记住运行之间的最后保存位置。为此,在ProjectName -> Properties -> Settings.settings下的Visual Studios Solution Explorer中,我设置了以下属性:

Settings.settings property: Name=PreviousPath, Type=string, Scope=User, leave Value empty

因为我在程序运行期间保持SaveFileDialog,所以我在开始时实例化。然后在Command中显示对话框:

if (string.IsNullOrEmpty(Settings.Default.PreviousPath))
{
    this.saveDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
else
{
    this.saveDialog.InitialDirectory = Settings.Default.PreviousPath;
}

this.saveDialog.FileName = "Default_File_Name";

bool result = this.saveDialog.ShowDialog() ?? false;

if (result)
{
    Settings.Default.PreviousPath = Path.GetDirectoryName(this.saveDialog.FileName);
    Settings.Default.Save();

    // Code writing to the new file...
}

这给出了行为:

  • 首次运行程序并打开对话框,它会导航到"我的文档"。
  • 连续运行并打开对话框:
    • 如果保存在之前打开的位置,则导航到上一个保存位置。
    • 如果未保存在之前的打开状态,请导航至"我的文档"。

答案 5 :(得分:1)

建议的解决方法对我不起作用,所以在找到How does WPF OpenFileDialog track directory of last opened file?后我实施了:

public static void SetInitialDirectory(this FileDialog dlg, string fileExtension, string initialDirectory)
        {
            // RestoreDirectory doesn't seem to be implemented - https://stackoverflow.com/questions/11144770/how-does-wpf-openfiledialog-track-directory-of-last-opened-file
            // so manually only set InitialDirectory if nothing is stored
            try
            {
                var mru = @"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\" + fileExtension;
                var rk = Registry.CurrentUser.OpenSubKey(mru);
                if (rk == null)
                {
                    dlg.InitialDirectory = initialDirectory;
                }
            }
            catch (Exception)
            {
                // SecurityException, ObjectDisposedException => allow default behaviour
            }
        }

如果此文件扩展名之前尚未使用该对话框,则将使用提供的initialDirectory。使用该对话框后,它将恢复为记住上一个目录的默认行为。

答案 6 :(得分:1)

我发现将InitialDirectory设置为null首先适用于用户历史记录。

    OpenFileDialog dlgOpen = new OpenFileDialog();
    dlgOpen.InitialDirectory = null;
    dlgOpen.InitialDirectory = @"c:\user\MyPath";

答案 7 :(得分:0)

我使用.NET 2.0进行了一些测试,似乎如果我将FileName设置为除文字字符串以外的任何内容,它都不起作用。当我使用方法或访问者设置属性时,将忽略初始目录。

答案 8 :(得分:0)

如果在路径中的任何位置使用正斜杠,则InitialDirectory不起作用。确保它们被转换为反斜杠

答案 9 :(得分:0)

savefiledialog.InitialDirectory = Application.StartupPath;
savefiledialog.RestoreDirectory = true;

在一秒钟前测试过。

答案 10 :(得分:0)

这就是我最终的结果,这与OP想要指向对话的地方一致:

Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.InitialDirectory = null;

// May or may not want "saves", but this shows how to append subdirectories
string path = (Path.Combine(Environment.ExpandEnvironmentVariables("%USERPROFILE%"), "My Documents") + "\\saves\\");  

if (!Directory.Exists(path))
    Directory.CreateDirectory(path);

dlg.InitialDirectory = path;
dlg.RestoreDirectory = true;

if (dlg.ShowDialog().Value == true)
{
    // This is so you can have JUST the directory they selected
    path = dlg.FileName.Remove(dlg.FileName.LastIndexOf('\\'), dlg.FileName.Length - dlg.FileName.LastIndexOf('\\'));

    string filePath = Path.Combine(path, fileName);

    // This is "just-in-case" - say they created a new directory in the dialog,
    // but the dialog doesn't seem to think it exists because it didn't see it on-launch?
    if (!Directory.Exists(path))
        Directory.CreateDirectory(path);

    // Remove a file if it has the same name
    if (File.Exist(filePath))
        File.Delete(filePath);

    // Write the file, assuming you have and pass in the bytes
    using (FileStream fs = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write)
    {
        fs.Write(bytes, 0, (int)bytes.Length);
        fs.Close();
    }
}

答案 11 :(得分:0)

因为我也遇到了确切的问题,所以只想对这个讨论(太晚了几年)进行评估。 即使有人认为这种行为 - 即第一次使用默认路径,然后是之后的前一个选定路径 - 可以通过使用openFileDialog的属性和函数来实现,但根本不能(现在)!

可以将工作目录更改为所需的默认路径 (例如Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);) 但是像Unity这样的一些框架并不喜欢这种框架并终止。

因此我最终得到了这段代码:

private bool firstDialogOpened = true;

public void BrowseFiles()
{
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "Model files (*.obj)|*.obj|All files (*.*)|*.*";
    openFileDialog.FilterIndex = 1;

    if (firstDialogOpened)
    {
        openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        firstDialogOpened = false;
    }

    if (openFileDialog.ShowDialog() == DialogResult.OK)
        filepath.text = openFileDialog.FileName;
}

这给了我理想的行为,虽然我会喜欢更优雅的解决方案。

答案 12 :(得分:0)

'在将输出文件保存到vb.net中的所需目录方面, '以下是我发现它像魅力一样的方式:

Dim filcsv As String = fileNamey.Replace(".txt", "_Denied2.csv")
Dim filcsv2 As String = fileNamey.Replace(".txt", "_Approved2.csv")

Dim outputDirectory As String = "C:\Users\jlcmil\Documents\EnableMN\output\"
Dim totalPath As String = System.IO.Path.Combine(outputDirectory, filcsv)
Dim totalPath2 As String = System.IO.Path.Combine(outputDirectory, filcsv2)

Dim outDenied As StreamWriter = New StreamWriter(totalPath)
Dim outApproved As StreamWriter = New StreamWriter(totalPath2)

答案 13 :(得分:0)

按如下所示使用saveFileDialog.InitialDirectory属性:

Stream stream;
SaveFileDialog saveFileDialog = new SaveFileDialog();

saveFileDialog.Filter = "dat files (*.dat)|*.dat|All files (*.*)|*.*";
saveFileDialog.FilterIndex = 1;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.InitialDirectory = @"D:\Data\...\foldername\";
saveFileDialog.ShowDialog();

if (!saveFileDialog.FileName.Equals(string.Empty))
    Console.WriteLine(saveFileDialog.FileName);

答案 14 :(得分:0)

如果有人希望以正确方式执行此操作...只需按照这篇 MSDN 文章进行操作,一切都会正常进行: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog.initialdirectory?view=net-5.0

是的:这可以动态完成...跟踪的聪明方法是使用文本框控件作为“最后一个路径”引用...请注意,大多数界面已经在表单上显示了路径文本框,在这种情况下,只需使用那个......如果文件夹不存在,请注意这里的回退到 MyDocuments......

示例:

您在此处的表单应具有典型的 LabelTextBox 和“浏览”Button 三重奏,用于 2 种不同的文件路径查找,但正如您所见,我使用相同的 { {1}} 实例以在按下各自的浏览按钮时设置这两个对话框:

OpenFileDialog