Select Either a File or Folder from the Same Dialog in .Net

Select either a file or folder from the same dialog in .NET

Technically, it is possible. The shell dialog used by FolderBrowseDialog has the ability to return both files and folders. Unfortunately, that capability isn't exposed in .NET. Not even reflection can poke the required option flag.

To make it work, you'd have to P/Invoke SHBrowseForFolder() with the BIF_BROWSEINCLUDEFILES flag turned on in BROWSEINFO.ulFlags (value = 0x4000). The P/Invoke is gritty, it is best to copy and paste the code from another source or the FolderBrowseDialog class itself with Reflector's help.

c# select Folders or Files in the same method

This is the easiest way I've found of solving this problem without relying on third party code, but you'll need to add some sanity checks, in case the user goofs around with the input:

        OpenFileDialog ofd = new OpenFileDialog();
ofd.CheckFileExists = false;
string defaultFilename = "Select this folder";
ofd.FileName = defaultFilename;

if (ofd.ShowDialog().Value)
{
// Check if the user picked a file or a directory, for example:
if (!ofd.FileName.Contains(defaultFilename))
{
// File code
}
else // You should probably turn this into an else if instead
{
// Directory code
}
// Alternatively, but still as unsafe
if (File.Exists(ofd.FileName))
{
// File code
}
else
{
// Directory code
}
}

Basically, the "trick" here is to set OpenFileDialog's CheckFileExists to false.

Is there a dialog to select a mixture of multiple files and folders at once?

Below is a screenshot of the UI and some snippets of code (mostly event handlers) tied to the implementation of a file AND folder selection dialog I mentioned in my comment.

While all of the code related to navigating directories and actually retrieving filepaths is in a different layer of code (a wrapper around a version control API), this should give you an idea of how one might implement a file AND folder selection dialog with multiple item select enabled from a controls perspective. A simple button to zip the current selection could call GetSourceSelectedFilePaths (or whatever you might choose to call it) and then zip all those paths together.

I suspect the System.IO.Directoryclass contains almost all of the methods you would need to handle the file / directory navigation side of this.

This certainly isn't much aesthetically and I'm aware you are not keen on implementing this yourself, but it certainly is possible (and relatively easy if you can live with something that looks like this). If I had more time I would have replaced all those API wrapper calls with System.IO.Directory method calls to make this a bit more clear.

Basic File / Folder Browser Dialog

// Method to display contents at current level (folders and files) to controls
private void AddToDisplayChildFolderContents(APIObject curVaultWrapper, ListBox childFolder_LB, ListBox childFiles_LB)
{
var curDocNames = curVaultWrapper.GetCurFolderDocNames(); // API wrapper call to get all documents in current folder

if (curDocNames.Count > 0)
{
childFiles_LB.Items.Clear();
childFiles_LB.Items.AddRange(curDocNames.ToArray());
}

var childFolderList = = curVaultWrapper.GetCurChildFolderNames(); // API wrapper call to get all folders in current folder
if (childFolderList.Count > 0)
{
childFolder_LB.Items.Clear();
childFolder_LB.Items.AddRange(returnStatus.items.ToArray());
}
}

// Method to navigate up one directory
private void srcGoUp_B_Click(object sender, EventArgs e)
{
if (VaultCopyConfig.SrcVault.DrillOutOfVaultFolder()) // API wrapper method returns true if current folder is root, points version controlled file system API wrapper one directory up
{
this.srcGoUp_B.Enabled = false;
}

DisplayVaultFolderContents(VaultCopyConfig.SrcVault, srcCurrentFolder_TB, srcDrill_IntoSubFolder_CB,
srcChildFolders_LB, srcFiles_LB);
}

// Method to navigate one directory lower
private void srcDrill_IntoSubFolder_CB_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedSubFolderName = srcDrill_IntoSubFolder_CB.Text;

VaultCopyConfig.SrcVault.DrillIntoVaultFolder(selectedSubFolderName, false); // call to our API wrapper

DisplayVaultFolderContents(vaultCopyConfig.srcVault, srcCurrentFolder_TB, srcDrill_IntoSubFolder_CB,
srcChildFolders_LB, srcFiles_LB);

this.srcGoUp_B.Enabled = true;
}

// Method that is called to aggregate all user selections (then sends to our API wrapper to actually validate / process / consolidate paths
private List<string> GetSourceSelectedFilePaths(bool dlgFlag)
{
var filePaths = new List<string>();

var validFolderNames = new List<string>();
var validFileNames = new List<string>();

if (srcChildFolders_LB.Items.Count > 0)
{
string selectedItem;
foreach (int i = 0; i < srcChildFolders_LB.Items.Count; i++)
{
if (srcChildFolders_LB.GetSelected(i))
{
selectedItem = srcChildFolders_LB.Items[i].ToString();
validFolderNames.Add(selectedItem);
}
}
}
if (srcFiles_LB.Items.Count > 0)
{
var selectedItem;
for (int i = 0; i < srcFiles_LB.Items.Count; i++)
{
if (srcFiles_LB.GetSelected(i))
{
selectedItem = srcFiles_LB.Items[i].ToString();
validFileNames.Add(selectedItem);
}
}
}

filePaths = VaultCopyConfig.SrcVault.GetSelectedFilePaths(validFolderNames, validFileNames, dlgFlag); // call to API wrapper to validate / consolidate list of all filepaths in user selection

return filePaths;
}

How do I use OpenFileDialog to select a folder?

As a note for future users who would like to avoid using FolderBrowserDialog, Microsoft once released an API called the WindowsAPICodePack that had a helpful dialog called CommonOpenFileDialog, that could be set into a IsFolderPicker mode. The API is available from Microsoft as a NuGet package.

This is all I needed to install and use the CommonOpenFileDialog. (NuGet handled the dependencies)

Install-Package Microsoft.WindowsAPICodePack-Shell

For the include line:

using Microsoft.WindowsAPICodePack.Dialogs;

Usage:

CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = "C:\\Users";
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
MessageBox.Show("You selected: " + dialog.FileName);
}


Related Topics



Leave a reply



Submit