Datagridview comboboxcell 不会设置为 readonly = false

Datagridview comboboxcell will not set to readonly = false

我有一个带有列(端口)的数据网格视图,我想用它来显示本地子网上机器上的可用端口。如果有一个或更少的端口,我使用文本框单元格 - 如果超过 1 个,我使用组合框单元格。组合框单元格拒绝删除,只读 属性 拒绝真实。在下面的代码中,您将看到我当前正在将列和单元格设置为 readonly = true,但快速观察表明它仍然设置为 false。

我已经记不清在代码或数据网格设置中尝试过的变体数量了。我使用过数据绑定、组合框列以及本论坛和其他论坛上建议的许多版本的代码。

我可能在做一些愚蠢的事情。任何帮助将不胜感激。

        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

我提供了该程序的屏幕转储以供参考。

Screen dump of program

约翰·哈德利

正在为组合框分配一个值,而不是一个列表。

使用

c.Items.AddRange(PortList.Cast<String>); 代替 c.Value = PortList[0]

您的代码很好,但缺少一两件事:

一个DataGridViewCell只是一个稍微改进的对象。它不是Control,无论它支持哪种编辑风格。

事件a 'simple' TextBoxCell只是真正的TextBox.

的占位符

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

每个编辑样式都通过将适当的编辑控件添加到 DataGridViewControls 集合来工作。当 DGV 进入编辑模式时,您可以观察如何添加一个控件。

并调整该控件使其工作方式不同于默认提供的控件,您需要访问实际的编辑控件,而不是单元格![=2​​4=]

为此,您需要编写 EditingControlShowing 事件代码:

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;
    }
}

现在我们已经将 ComboBoxStyleDropDownList 更改为 DropDown 单元格是可编辑的。

通常您希望保留输入的值;为此编写 CellValidating 事件代码:

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);
}

两件事。

首先 - 我很尴尬。整个网格已被设置回只读状态(不是几天前),所以我不确定过去几天我尝试过的任何事情是否能解决问题。将 DataGridView 设置为 readonly = false 后问题仍然存在。

其次 - TaW - 感谢您的建议。它看起来已经解决了我的问题。我需要确保更改了正确的单元格,但我现在有下拉组合框。谢谢。

约翰·哈德利