Home > Software design >  How do I open the path of an item in a combobox while also only displaying the file name?
How do I open the path of an item in a combobox while also only displaying the file name?

Time:09-29

I am searching for exe files in a folder and displaying the file names in a combobox to be selected by the user. When the user presses a button the file selected should be opened. This works if I display the file path rather than the file name in the combobox.

public void Form1_Load(object sender, EventArgs e)
{

    string[] filePaths = Directory.GetFiles(@"C:\myFolder\", "*.exe");
    foreach (string file in filePaths)
    {
        comboBox1.Items.Add(Path.GetFileNameWithoutExtension(file));
    }
}

private void button1_Click(object sender, EventArgs e)
{
    object b = comboBox1.SelectedItem;
    string be = Convert.ToString(b);
    System.Diagnostics.Process.Start(be);
}

CodePudding user response:

For the program to be executed you need the entire path. For the display it should suffice to give the user a name for orientation. Now the only thing left is to map one to the other. For this you could use a simple dictionary. Collect all names as keys and the corresponding paths as values. Display only the names.

private Dictionary<string, string> map = new Dictionary<string, string>();

public void Form1_Load(object sender, EventArgs e)
{

    string[] filePaths = Directory.GetFiles(@"C:\myFolder\", "*.exe");
    foreach (string fullPath in filePaths)
    {
        string displayName = Path.GetFileNameWithoutExtension(fullPath);
        map.Add(displayName, fullPath);
        comboBox1.Items.Add(displayName);
    }
}

Then retrieve the path from the dictionary using the name as the key

private void button1_Click(object sender, EventArgs e)
{
    string nameKey = comboBox1.SelectedItem.ToString();
    string executablePath = map[nameKey];
    System.Diagnostics.Process.Start(executablePath);
}

Edit:

As suggested by Panagiotis Binding example:

To use binding you would need to specify what is displayed and what is treated as value in the combobox. You do that by telling the DisplayMember and ValueMember which property of the dictionary it should use. Furthermore the dictionary has to be encompassed by a BindingSource.

public void Form1_Load(object sender, EventArgs e)
{

    string[] filePaths = Directory.GetFiles(@"C:\myFolder\", "*.exe");
    foreach (string fullPath in filePaths)
    {
        string displayName = Path.GetFileNameWithoutExtension(fullPath);
        map.Add(displayName, fullPath);
    }

    comboBox1.DisplayMember="Key";
    comboBox1.ValueMember="Value";
    comboBox1.DataSource= new BindingSource(map, null);
}

In this example you would need to use the SelectedValue propertyto retrieve the value of the dictionary item, hence the full path. You can use it directly

private void button1_Click(object sender, EventArgs e)
{        
    System.Diagnostics.Process.Start(comboBox1.SelectedValue.ToString());
}

CodePudding user response:

You don't need to put strings into the ComboBox - you can put other objects in, and the ComboBox will use .ToString() to get the string to display.

That means you can write a wrapper class like so to include the information you need:

public sealed class FileInformation
{
    public FileInformation(string fullFilename)
    {
        FullFilename = fullFilename;
        Filename = Path.GetFileNameWithoutExtension(fullFilename);
    }

    public override string ToString()
    {
        return Filename;
    }

    public string FullFilename { get; }
    public string Filename { get; }
}

Then your code to populate the ComboBox would look something like this:

string[] filePaths = Directory.GetFiles(@"C:\bin\", "*.exe");
foreach (string file in filePaths)
{
    comboBox1.Items.Add(new FileInformation(file));
}

And the button handler could look like this:

var info = (FileInformation) comboBox1.SelectedItem;
System.Diagnostics.Process.Start(info.FullFilename);

CodePudding user response:

Use data binding instead of adding items one by one, and specify which property you want to display using the DisplayMember property. How to: Bind a Windows Forms ComboBox or ListBox Control to Data shows how data binding works.

One option is to load the list of all files as FileInfo objects and set them to the combo's DataSource property, and use Name as the DisplayMember:

FileInfo[] _files=Array.Empty<FileInfo>();

public void Form1_Load(object sender, EventArgs e)
{
    comboBox1.DisplayMember="Name";
    var folder=new DirectoryInfo(@"C:\myFolder\");
    _files=folder.GetFiles("*.exe");
   comboBox1.DataSource=_files;
}

private void button1_Click(object sender, EventArgs e)
{
    var file = (FileInfo)comboBox1.SelectedItem;
    System.Diagnostics.Process.Start(file.FullName);
}

You can set the DisplayMember in the combo's properties too.

FileInfo doesn't have a property to return the name without an extension and DisplayMember doesn't accept expressions. If you need to display the name, you can create your own class to hold the file and name:


class MyFile
{
    public FileInfo File {get;set;}
    public string Name=>Path.GetFileNameWithoutExtension(File.FullName);
}


    MyFile[] _files=Array.Empty<MyFile>();

    public void Form1_Load(object sender, EventArgs e)
    {
        comboBox1.DisplayMember="Name";
        var folder=new DirectoryInfo(@"C:\myFolder\");
        _files=folder.EnumerateFiles("*.exe")
                     .Select(f=> new MyFile{File=file})
                     .ToArray();
       comboBox1.DataSource=_files;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var file = (MyFile)comboBox1.SelectedItem;
        System.Diagnostics.Process.Start(file.File.FullName);
    }
  • Related