5

I remember in vb6 there was a control that was similar to a dropbox/combobox that you can select the drive name. It raises an event which you can then set another control which enumerate files in listbox. (in drive.event you do files.path = drive.path to get this affect).

Is there anything like this in C#? a control that drops down a list of available drives and raises an event when it is changed?

  • There are valid reasons why you need to be able to list the drives available to the system: for instance we need to be able to configure a system to charge different amounts of money depending on which drive the user chooses to save to. (No, I don't think it's a good idea, but the customer insists). – Jedidja Mar 02 '11 at 05:40

4 Answers4

14

There's no built-in control to do that, but it's very easy to accomplish with a standard ComboBox. Drop one on your form, change its DropDownStyle to DropDownList to prevent editing, and in the Load event for the form, add this line:

comboBox1.DataSource = Environment.GetLogicalDrives();

Now you can handle the SelectedValueChanged event to take action when someone changes the selected drive.

After answering this question, I've found another (better?) way to do this. You can use the DriveInfo.GetDrives() method to enumerate the drives and bind the result to the ComboBox. That way you can limit which drives apppear. So you could start with this:

comboBox1.DataSource = System.IO.DriveInfo.GetDrives();
comboBox1.DisplayMember = "Name";

Now comboBox1.SelectedValue will be of type DriveInfo, so you'll get lots more info about the selected game. And if you only want to show network drives, you can do this now:

comboBox1.DataSource = System.IO.DriveInfo.GetDrives()
    .Where(d => d.DriveType == System.IO.DriveType.Network);
comboBox1.DisplayMember = "Name";

I think the DriveInfo method is a lot more flexible.

Community
  • 1
  • 1
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • strangely this gave me *"A first chance exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll"* so if i use this in try catch i guess it would be better. – Berker Yüceer Jun 07 '12 at 10:17
3

While Matt Hamiltons answer was very correct, I'm wondering if the question itself is. Because, why would you want such a control? It feels very Windows 95 to be honest. Please have a look at the Windows User Experience Interaction Guidelines: http://msdn.microsoft.com/en-us/library/aa511258.aspx

Especially the section about common dialogs: http://msdn.microsoft.com/en-us/library/aa511274.aspx

Commander Keen
  • 742
  • 6
  • 12
  • It was a solution i used in the past and i was afraid of emulating the functionality as i am use to doing so in c++ :(. Also i am very new at C# and never would of thought the answer is as simple as Matt solution –  Mar 08 '09 at 07:36
1

I would approach this with:

foreach (var Drives in Environment.GetLogicalDrives())
{
    DriveInfo DriveInf = new DriveInfo(Drives);
    if (DriveInf.IsReady == true)
    {
        comboBox1.Items.Add(DriveInf.Name);
    }
}

With the help of Drive.IsReady u can avoid having DeviceNotReady or DeviceUnavailable issues.

Bonus: Also here is a simple "ChooseFile" example which includes a ComboBox for drives, a TreeView for folders and the last a ListBox for files.

namespace ChosenFile
{
    public partial class Form1 : Form
    {
        // Form1 FormLoad
        //
        public Form1()
        {
            InitializeComponent();
            foreach (var Drives in Environment.GetLogicalDrives())
            {
                DriveInfo DriveInf = new DriveInfo(Drives);
                if (DriveInf.IsReady == true)
                {
                    comboBox1.Items.Add(DriveInf.Name);
                }
            }
        }

        // ComboBox1 (Drives)
        //
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedItem != null)
            {
                ListDirectory(treeView1, comboBox1.SelectedItem.ToString());
            }
        }

        // ListDirectory Function (Recursive Approach):
        // 
        private void ListDirectory(TreeView treeView, string path)
        {
            treeView.Nodes.Clear();
            var rootDirectoryInfo = new DirectoryInfo(path);
            treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
        }
        // Create Directory Node
        // 
        private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
        {
            var directoryNode = new TreeNode(directoryInfo.Name);
            try
            {
                foreach (var directory in directoryInfo.GetDirectories())
                    directoryNode.Nodes.Add(CreateDirectoryNode(directory));
            }
            catch (Exception ex)
            {
                UnauthorizedAccessException Uaex = new UnauthorizedAccessException();
                if (ex == Uaex)
                {
                    MessageBox.Show(Uaex.Message);
                }
            }
            return directoryNode;
        }

        // TreeView
        // 
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            listBox1.Items.Clear();
            listBox1.Refresh();
            PopulateListBox(listBox1, treeView1.SelectedNode.FullPath.ToString(), "*.pdf");
        }
        // PopulateListBox Function
        // 
        private void PopulateListBox(ListBox lsb, string Folder, string FileType)
        {
            try
            {
                DirectoryInfo dinfo = new DirectoryInfo(Folder);
                FileInfo[] Files = dinfo.GetFiles(FileType);
                foreach (FileInfo file in Files)
                {
                    lsb.Items.Add(file.Name);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while attempting to load the file. The error is:"
                                + System.Environment.NewLine + ex.ToString() + System.Environment.NewLine);
            }
        }

        // ListBox1
        //
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedItem != null)
            {
                //do smt here!
                MessageBox.Show(listBox1.SelectedItem.ToString());
            }
        }
    }
}

Just like the old times in VB6.

Berker Yüceer
  • 7,026
  • 18
  • 68
  • 102
0

A comboBox and this little code will do the job. Kindest regards! Luis:

    comboBox1.DataSource = System.IO.DriveInfo.GetDrives()
        .Where(d => d.DriveType == System.IO.DriveType.Network).ToList();
    comboBox1.DisplayMember = "Name";
luismaf
  • 1
  • 2