Reputation: 5449
I'd like a SaveFileDialog with the following behavior:
The first time you open it, it goes to "My Documents".
Afterwards, it goes to the last selected folder. What's the best way to accomplish this?
If I don't set the InitialDirectory, it goes to the exe's directory - which is not what I want. It rememebers the last selected directory though - even between executions.
If I set the InitialDirectory, it does not remember the last selected directory. Of course, I could save the last selected directory in the registry :( but I am looking for a better solution.
SaveFileDialog dialog = new SaveFileDialog();
//??? dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dialog.ShowDialog();
Any advice?
Upvotes: 40
Views: 70573
Reputation: 1916
In case anyone is looking to do this the proper way... just follow this MSDN article and everything will work properly: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog.initialdirectory?view=net-5.0
And yes: this can be done dynamically... smart way to keep track is to use a textbox control as a "last path" reference... mind you most interfaces will already be showing a path textbox on the form, in which case, just use that one... note also here the fallback to MyDocuments if the folder does not exist...
Example:
Your form here is expected to have your typical Label
, TextBox
and "Browse" Button
trio for 2 different file path lookups, but as you can see I use the same OpenFileDialog
instance to setup both dialogs when their respective browse buttons are pushed:
private void btn_KnownServersFilePath_Browse_Click(object sender, EventArgs e)
{
string tmppath = Path.GetDirectoryName(this.txt_Servers_TemplatePath.Text) + "\\";
this.openFileDialog1.InitialDirectory = Directory.Exists(tmppath) ? tmppath : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
this.openFileDialog1.Filter = "excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
this.openFileDialog1.FilterIndex = 2;
this.openFileDialog1.RestoreDirectory = true;
this.openFileDialog1.FileName = Path.GetFileName(this.txt_Servers_TemplatePath.Text);
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
this.txt_Servers_TemplatePath.Text = this.openFileDialog1.FileName;
}
private void btn_ServerDumpFilePath_Browse_Click(object sender, EventArgs e)
{
string tmppath = Path.GetDirectoryName(this.txt_AllOU_TemplatePath.Text) + "\\";
this.openFileDialog1.InitialDirectory = Directory.Exists(tmppath) ? tmppath : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
this.openFileDialog1.Filter = "AD dump files (*.csv)|*.csv|All files (*.*)|*.*";
this.openFileDialog1.FilterIndex = 2;
this.openFileDialog1.RestoreDirectory = true;
this.openFileDialog1.FileName = Path.GetFileName(this.txt_AllOU_TemplatePath.Text);
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
this.txt_AllOU_TemplatePath.Text = this.openFileDialog1.FileName;
}
Upvotes: 0
Reputation: 984
use the saveFileDialog.InitialDirectory
property as follows:
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);
Upvotes: 0
Reputation: 1
'In terms of saving an output file to a desired directory in vb.net, 'the following was the way I found that worked like a charm:
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)
Upvotes: 0
Reputation: 1
Just wanted to weigh in on this discussion (a couple of years too late) as I had exact problem too. Even though one is led to believe that this behavior - i.e using a default path the first time and then the previous selected path after that - can be achieved by using openFileDialog's properties and functions, one simply can't (per now)!
One could change the working directory to the desired default path
(e.g. Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
)
but some framework, like Unity, doesn't like this very much and terminates.
Because of this I ended up with this code:
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;
}
This gives the desired behavior for me, although I would have loved a more elegant solution.
Upvotes: 0
Reputation: 7537
This is what I ended up with, that goes along with where the OP wanted to point their dialog:
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();
}
}
Upvotes: 0
Reputation: 21
I found that setting InitialDirectory
to null
first works around user history.
OpenFileDialog dlgOpen = new OpenFileDialog();
dlgOpen.InitialDirectory = null;
dlgOpen.InitialDirectory = @"c:\user\MyPath";
Upvotes: 2
Reputation: 8653
The suggested workarounds didn't work for me, so after finding How does WPF OpenFileDialog track directory of last opened file? I implemented:
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
}
}
This will use the provided initialDirectory if the dialog has not been used before for this file extension. Once the dialog has been used, it reverts to the default behaviour of remembering the previous directory.
Upvotes: 2
Reputation: 5454
None of the provided solutions worked for me sadly.
In addition to the OP specifications, I wanted the program to remember the last save location between runs. For this, in the Visual Studios Solution Explorer under ProjectName -> Properties -> Settings.settings
, I setup the following property:
Because I am keeping the SaveFileDialog
around for the duration of the program's running, I instantiate at the start. Then in the Command
for bringing up the dialog:
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...
}
This gives the behavior:
Upvotes: 1
Reputation: 423
savefiledialog.InitialDirectory = Application.StartupPath;
savefiledialog.RestoreDirectory = true;
tested a second ago.
Upvotes: 0
Reputation: 794
If you use forward slash anywhere in your path, InitialDirectory does not work. Make sure they are converted to back slashes
Upvotes: 0
Reputation: 81
Make sure to check that the directory path exists before setting the Initial directory property. Create the directory if it does not exist. ie
if (!Directory.Exists(FooDirectory))
{
Directory.CreateDirectory(FooDirectory);
}
Upvotes: 5
Reputation: 10337
I too have tried different "solutions" found in different places, but none of them seem to work as soon as there is an MRU list entry in the registry :/ But here is my own simple workaround…
Instead of setting the dialog's InitialDirectory
property, set the FileName
property to your path, but combined with the selected Filter
, e.g.:
dialog.FileName = Path.Combine(myPath, "*.*");
Upvotes: 3
Reputation: 2437
I have no idea why this works, but I was finally able to get it working for me.
I found that if I gave the full path, it would not work, but if I put that full path inside of Path.GetFullPath(), then it would work. Looking at the before and after values show them being the same, but it would consistently not work without it, and work with it.
//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;
Upvotes: 22
Reputation: 3950
I did some testing with .NET 2.0 and it seems if I set FileName to anything other than a literal string it doesn't work. When I use a method or accesstor to set the property the initial directory is ignored.
Upvotes: 0
Reputation: 351476
You need to set the RestoreDirectory
to true
as well as the InitialDirectory
property.
Upvotes: 37