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.
John Hadley
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);
}