2

I have a datagridview with a column (Ports) that I want to use to dislay available ports on machines on my local subnet. If there is one or less port I use a textbox cell - if more than 1 I use a comboboxcell. The combobox cell refuses to drop and the read only property refuses to be anything but true. In the code below you will see I am currently setting the column, and cell to readonly = true, but a quick watch says it is still set to false.

I have lost count of the number of variations I have tried in code or the setup of the datagrid. I have used data binding, a combobox column, and many versions of code suggested on this forum and others.

I am probably doing something stupid. Any help would be appreciated.

        void AddRowFromScanSubnet(List<Machine> Machines)
    {
        dgComputers.Rows.Clear();
        lblItems.Text = Machines.Count.ToString();
        Machines.Sort(delegate (Machine x, Machine y)
        {
            if (x.ipaddress == null && y.ipaddress == null) return 0;
            else if (x.ipaddress == null) return -1;
            else if (y.ipaddress == null) return 1;
            else return x.ipaddress.CompareTo(y.ipaddress);
        });
        try
        {
            for (int i = 0; i < Machines.Count; i++)
            {
                string IPAddr = "Unknown";
                string MacAddr = "Unknown";
                string HostName = "Unknown";
                string Roll = "Unknown";
                List<string> PortList = new List<string>();
                string misc = "";
                string OS = "Unknown";
                string Status = "Unk";
                if (Machines[i].ipaddress != null) IPAddr = Machines[i].ipaddress;
                if (Machines[i].macaddress != null) MacAddr = Machines[i].macaddress;
                if (Machines[i].hostname != null) HostName = Machines[i].hostname;
                if (Machines[i].roll != null) Roll = Machines[i].roll;
                if (Machines[i].portlist != null) PortList = Machines[i].portlist;
                if (Machines[i].misc != null) misc = Machines[i].misc;
                if (Machines[i].OS != null) OS = Machines[i].OS;
                if (Machines[i].portlist != null) PortList = Machines[i].portlist;
                if (Machines[i].status != null) Status = Machines[i].status;
                if (PortList.Count == 0) PortList.Add("none");

                int number = dgComputers.Rows.Add();
                dgComputers.Rows[number].Cells[0].Value = IPAddr;
                dgComputers.Rows[number].Cells[1].Value = MacAddr;
                dgComputers.Rows[number].Cells[2].Value = HostName;
                dgComputers.Rows[number].Cells[3].Value = OS;
                dgComputers.Rows[number].Cells[4].Value = Roll;
                dgComputers.Columns[5].ReadOnly = false;
                if (PortList.Count < 2)
                {
                    dgComputers.Rows[number].Cells[5].Value = PortList[0];
                }
                else
                {
                    DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
                    c.MaxDropDownItems = 10;
                    foreach (string s in PortList)
                    {
                        c.Items.Add(s);
                    }
                    c.Value = PortList[0];
                    c.ReadOnly = false;
                    dgComputers.Rows[number].Cells[5] = c;
                    dgComputers.Rows[number].Cells[5].ReadOnly = false;
                }
                dgComputers.Columns[5].ReadOnly = false;
                dgComputers.Rows[number].Cells[6].Value = Status;
                dgComputers.Rows[number].Cells[7].Value = misc;
                dgComputers.Columns[5].ReadOnly = false;
                dgComputers.Rows[number].Cells[5].ReadOnly = false;
            }
        }
        catch (Exception ex)
        {
            string msg = "AddRowFromScanSubnet - " + ex.ToString();
        }
        Thread.Sleep(1000);
    }

Datagridview column properties

I have included a screen dump of the program for information.

Screen dump of program

John Hadley

TaW
  • 53,122
  • 8
  • 69
  • 111
  • is `PortList[]` an array of ports? if so, you are only assigning a single value to the cell. – Takarii Feb 01 '16 at 14:34
  • Check out the code above.If PortList only contains 1 item I add 1 item to a text box. If there are mor than 1 items I use a combobox and foreach (... in PortList) {c.Items.Add()} so I am adding as many items as are in PortList. – John Hadley Feb 02 '16 at 16:35

3 Answers3

2

Your code is fine but missing one or two things:

A DataGridViewCell is just a slightly improved object. It is not a Control, no matter which edit style it supports.

Event a 'simple' TextBoxCell is only a placeholder for a real TextBox.

 System.Object
   System.Windows.Forms.DataGridViewElement
     System.Windows.Forms.DataGridViewCell

Each edit style works by adding the appropriate edit control to the Controls collection of the DataGridView. You can observe how one controls is added whenever the DGV goes into edit mode.

And to tweek that control to work differently than what the default provides you need to access the actual edit control, not the cell!

To do so you need to code the EditingControlShowing event:

private void dgComputers_EditingControlShowing(object sender, 
                         DataGridViewEditingControlShowingEventArgs e)
{
    // mabye add checks to see if you want to make this one editable!?
    {
        ComboBox combo = e.Control as ComboBox;
        if (combo != null)  combo.DropDownStyle = ComboBoxStyle.DropDown;
    }
}

Now that we have changed the ComboBoxStyle from DropDownList to DropDown th cell is editable.

Often you want to keep the entered values; to do so code the CellValidating event:

private void dgComputers _CellValidating(object sender,
                                         DataGridViewCellValidatingEventArgs e)
{
    // maybe add checks to see if this is the right one!?
    DataGridViewComboBoxCell comboCell =
        dgComputers[e.ColumnIndex, e.RowIndex] as DataGridViewComboBoxCell;
    if (comboCell != null)
        if (!comboCell.Items.Contains(e.FormattedValue))
            comboCell.Items.Add(e.FormattedValue);
}
TaW
  • 53,122
  • 8
  • 69
  • 111
  • That gives me drop down boxes. Thank you. I will have to do some validation as your comments suggest. Again thank you - I thinkI could have been trying to crack this one for quite some time. – John Hadley Feb 02 '16 at 15:44
0

The combobox is being assigned a value, not a list.

use

c.Items.AddRange(PortList.Cast<String>); in place of c.Value = PortList[0]

Takarii
  • 1,612
  • 2
  • 18
  • 29
0

Two things.

First - I am embarrased. The whole grid had beed set back to read only (it was not a few days ago), so I am unsure if anything I had tried over the past few days would have solved the problem. After setting the DataGridView to readonly = false the problem was still there.

Second - TaW - Thank you for your suggestion. It looks to have solved my problem. I need to make sure that the correct cells are changed, but I now have drop down comboboxes. Thank you.

John Hadley