Gravitate
Gravitate

Reputation: 3062

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

I realise that there are already a number of questions very similar to this:

multi select folders and files

C# Dialog to select multiple files AND folders

C# - How to customize OpenFileDialog to select multiple folders and files?

Required Dialog for selecting Multiple Files and Folders .NET

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

However, none have quite what I am looking for. Some solutions only work for selecting multiple files, others only for multiple folders. None that I am aware of allow the selection of a mixture of both at one time.

This looks to be exactly what I am looking for... Except that it is C++, and I have no idea how I could utilise it in .NET (is this a possibility):

https://www.codeproject.com/Articles/28015/SelectDialog-A-Multiple-File-and-Folder-Select-Dia

I realise that it is very unlikely for there to be a dialog built into .NET which I have overlooked. However, as I think it would be a fairly common requirement, I would have thought there would be something already made rather than me rolling my own. Which would take a relatively long time and probably end up being much more basic than the built in OpenFileDialog (all be it with the basic functionality we require).

My use case is that I require a dialog to select a number of individual files and folders return their paths so that they can be zipped together.

What is the quickest and easiest way for me to implement such a dialog in Winforms?

Upvotes: 2

Views: 1614

Answers (2)

Gravitate
Gravitate

Reputation: 3062

Even though, I haven't used any of the code supplied, I am going to accept @mdsimps99's answer, as the question was "What is the quickest and easiest way for me to implement such a dialog in Winforms?", and his answer was that I have to roll my own (unfortunately).

However, I thought I would post my less than ideal solution for completeness.

I didn't have time to do what I would like and produce a custom solution that completely emulates the OpenFileDialog. So instead, I produced a "SelectPathsDialog" that sits between my main program and the OpenFileDialog (and FolderBrowserDialog).

It is very simple:

enter image description here

The "Add Files" button opens the OpenFileDialog and adds the selected files to the list. The "Add Folders" button opens the FolderBrowserDialog and adds the selected folder to the list.

It mirrors all the public properties that I was already using from OpenFileDialog. This means that, in my main program, I was able to easily replace all calls to "OpenFileDialog", with "SelectPathsDialog", and it would function correctly.

I also added properties to enable or disable the appropriate buttons if I needed to only allow files to be selected for example.

As I plan to improve it in the future, I used the 3rd party ObjectListView control as it is far more versatile than the standard ListView.

As I say. It is not ideal. But it does the job for the time being and I can always revisit it at a later date when time pressures are't so great.

Upvotes: 1

user8061994
user8061994

Reputation:

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;
}

Upvotes: 1

Related Questions