0

I have a form application where multiple DataGridView objects are to be displayed (but not at once). They should be created on top of each other and it should then be possible to toggle the displayed DataGridView using a ComboBox. I have a function which should create new DataGridView every time its called and then adds the name to the ComboBox:

private void readCSV(string DBname)
{
    DataGridView tagDBname = new DataGridView();
    tagDBname.Location = new System.Drawing.Point(24, 260);
    tagDBname.Name = DBname;
    tagDBname.Size = new System.Drawing.Size(551, 217);
    tagDBname.TabIndex = 6;

    tagDBname.Columns.Add("Column1", "Col1");
    tagDBname.Columns.Add("Column2", "Col2");

    tagDBname.Visible = false;

    comboBoxTag.Items.Add(DBname);
}

Then I would like to change the visibility state of a DataGridView given the selected name from the ComboBox. This should be done in the function called when the index changes:

private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
    // Get the name of the DataGridView which should be visible:
    string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
    DataGridView tagDatabase = ? // Here the DataGridView should be selected given the name "selectedTagDB"

    tagDatabase.Visible = true;
}

In the above, I do not know how to assign the DataGridView only given its name. Any help would be appreciated - even if it means that the selected approach is inappropriate of what I am trying to achieve. If the question is answered elsewhere, feel free to guide me in the right direction :)

ChrisRun
  • 131
  • 1
  • 9

2 Answers2

4

I would store the gridviews in a dictionary by using the DB name as key;

private readonly Dictionary<string, DataGridView> _tagDBs =
    new Dictionary<string, DataGridView>();

private void readCSV(string DBname)
{
    DataGridView tagDBname = new DataGridView();

    // Add the gridview to the dictionary.
    _tagDBs.Add(DBname, tagDBname);

    tagDBname.Name = DBname;
    tagDBname.Location = new System.Drawing.Point(24, 260);
    tagDBname.Size = new System.Drawing.Size(551, 217);
    tagDBname.TabIndex = 6;

    tagDBname.Columns.Add("Column1", "Col1");
    tagDBname.Columns.Add("Column2", "Col2");

    tagDBname.Visible = false;

    this.Controls.Add(tagDBname); // Add the gridview to the form ot to a control.
    comboBoxTag.Items.Add(DBname);
}

private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
    // Get the name of the DataGridView which should be visible:
    string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();

    foreach (DataGridView dgv in _tagDBs.Values) {
        dgv.Visible = dgv.Name == selectedTagDB; // Hide all gridviews except the selected one.
    }
}

If you need to do something with the selected gridview, you can get it with:

if (_tagDBs.TryGetValue(selectedTagDB, out DataGridView tagDatabase)) {
    // do something with tagDatabase.
}

Note: you must add the gridview to the form or to a container control on the form. E.g.

this.Controls.Add(tagDBname);
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thanks for your answer. Do you know how I can determine on which tab the DGV should be displayed on? The form has a TabControl layout, and the DGV does not appear with this.Controls.Add(tagDBname). – ChrisRun May 10 '19 at 14:28
  • This requirement does not match your code. If the gridviews appear on different tab pages, you can make all of them visible right away and don't need a combobox for the selection as the user will select tab pages instead. This makes the selected gridview visible automatically. See [Dynamically add tabs to TabControl container](https://stackoverflow.com/questions/33069634/dynamically-add-tabs-to-tabcontrol-container). – Olivier Jacot-Descombes May 10 '19 at 14:35
  • All of the DGV created are supposted to be on one single tab on top of each other - and not different tabs. Am I missng an argument of which tab the DGV should be displayed on when I initialize the DGV? Because they do not appear on the form. – ChrisRun May 10 '19 at 14:38
  • 1
    Tab pages have names. E.g.: `tabPage1.Controls.Add(tagDBname);`. – Olivier Jacot-Descombes May 10 '19 at 14:45
  • Thank you so much, just the detail I was missing. Now everything works perfectly! :) – ChrisRun May 10 '19 at 14:48
2

You can loop through all DataGridViews of the form to display the expected one using its name, while hidding the others ones.

This solution isn't pretty but works

private void ShowOneDataGridViewAndHideOthers(string name)
{
    foreach (var DGV in this.Controls.OfType<DataGridView>())
    {
        DGV.Visible = DGV.Name == name;
    }
}

And call it this way :

private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
    // Get the name of the DataGridView which should be visible:
    string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
    ShowOneDataGridViewAndHideOthers(selectedTagDB);
}

The method can be made a bit more generic this way :

private void ShowOneControlAndHideOthers<T>(string name, Control controls) where T : Control
{
    foreach (var control in controls.Controls.OfType<T>())
    {
        control.Visible = control.Name == name;
    }
}

private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
    // Get the name of the DataGridView which should be visible:
    string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
    ShowOneControlAndHideOthers<DataGridView>(selectedTagDB, this);
}
Cid
  • 14,968
  • 4
  • 30
  • 45
  • Quite a pretty solution, just note that `this.Controls` needs the be the parent control of your DataGridViews. Using the dictionary approach below doesn't need to know the parent – Fixation May 10 '19 at 14:07