【问题标题】:Exception when adding a new row to my DataGridView向我的 DataGridView 添加新行时出现异常
【发布时间】:2016-06-07 10:11:26
【问题描述】:

我有这个问题。开头是这样的:

我可以双击下拉箭头并选择一种颜色 OK:

此时,我可以再次点击下拉菜单并正确选择:

问题是当我想添加新行时。即使我只是去点击新的行单元格:

然后我数据一个数据错误异常:

此后上一个单元格绘制不正确:

我不知道如何解决这个问题。

我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Teigha.Core;
using Teigha.TD;

namespace Viewer
{
    public partial class Editor : Form
    {
        uint[] _CurPalette = Teigha.Core.AllPalettes.getDarkPalette();

        public Editor()
        {
            InitializeComponent();
        }

        private void Editor_Load(object sender, EventArgs e)
        {
            DataGridViewComboBoxColumn cboColumn = new DataGridViewComboBoxColumn();
            cboColumn.Name = "Color";

            List<ushort> listColors = new List<ushort>();
            listColors.Add(1);
            listColors.Add(2);
            listColors.Add(3);
            listColors.Add(4);
            listColors.Add(5);
            listColors.Add(6);
            listColors.Add(7);
            listColors.Add(8);
            listColors.Add(9);
            listColors.Add(250);
            listColors.Add(251);
            listColors.Add(252);
            listColors.Add(253);
            listColors.Add(254);
            listColors.Add(255);

            foreach (ushort iColorIndex in listColors)
            {
                using (OdCmColor oColor = new OdCmColor())
                {
                    oColor.setColorIndex(iColorIndex);
                    ComboboxColorItem oColorItem = new ComboboxColorItem(
                        oColor.colorNameForDisplay(),
                        iColorIndex,
                        Color.FromArgb(oColor.red(), oColor.green(), oColor.blue()));
                    cboColumn.Items.Add(oColorItem);
                }
            }

            this.DataGridView1.Columns.Add(cboColumn);
        }

        private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is ComboBox)
            {
                ComboBox theCB = (ComboBox)e.Control;
                theCB.DrawMode = DrawMode.OwnerDrawFixed;
                try
                {
                    theCB.DrawItem -= new DrawItemEventHandler(this.combobox1_DrawItem);
                }
                catch { }
                theCB.DrawItem += new DrawItemEventHandler(this.combobox1_DrawItem);
            }
        }

        private void combobox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            Graphics g = e.Graphics;
            Color c = Color.Empty;
            string s = "";
            Brush br = SystemBrushes.WindowText;
            Brush brBack;
            Rectangle rDraw;
            bool bSelected = Convert.ToBoolean(e.State & DrawItemState.Selected);
            bool bValue = Convert.ToBoolean(e.State & DrawItemState.ComboBoxEdit);

            rDraw = e.Bounds;
            rDraw.Inflate(-1, -1);

            if (bSelected & !bValue)
            {
                brBack = Brushes.LightBlue;
                g.FillRectangle(Brushes.LightBlue, rDraw);
                g.DrawRectangle(Pens.Blue, rDraw);
            }
            else
            {
                brBack = Brushes.White;
                g.FillRectangle(brBack, e.Bounds);
            }

            try
            {
                //s = ((ComboBox)sender).Items[e.Index].ToString();
                ComboboxColorItem oColorItem = (ComboboxColorItem)((ComboBox)sender).Items[e.Index];
                s = oColorItem.ToString();
                c = oColorItem.Value;
            }
            catch
            {
                s = "red";
                c = Color.Red;
            }

            SolidBrush b = new SolidBrush(c);
            Rectangle r = new Rectangle(e.Bounds.Left + 5, e.Bounds.Top + 3, 10, 10);
            g.FillRectangle(b, r);
            g.DrawRectangle(Pens.Black, r);
            g.DrawString(s, Form.DefaultFont, Brushes.Black, e.Bounds.Left + 25, e.Bounds.Top + 1);

            b.Dispose();
            g.Dispose();
        }

        private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            MessageBox.Show(e.Exception.ToString());
        }
    }

    public class ComboboxColorItem
    {
        public string Name { get; }
        public ushort Index { get; }
        public Color Value { get; }

        public ComboboxColorItem(string Name, ushort Index, Color Value)
        {
            this.Name = Name;
            this.Index = Index;
            this.Value = Value;
        }
        public override string ToString()
        {
            return Name;
        }
    }
}

更新:

如果我将此代码放入表单加载事件中:

this.DataGridView1.Rows.Add(new ComboboxColorItem("red", 1, Color.Red));

然后我立即得到异常。

我尝试添加辅助默认构造函数,但没有任何区别:

public class ComboboxColorItem
{
    public string Name { get; set; }
    public ushort Index { get; set; }
    public Color Value { get; set; }

    public ComboboxColorItem()
    {
        this.Name = "red";
        this.Index = 1;
        this.Value = Color.Red;
    }
    public ComboboxColorItem(string Name, ushort Index, Color Value)
    {
        this.Name = Name;
        this.Index = Index;
        this.Value = Value;
    }
    public override string ToString()
    {
        return Name;
    }
}

我也尝试将其添加到加载事件中:

cboColumn.ValueType = typeof(ComboboxColorItem);

没有影响。

更新:

我使用了 CellParsing 答案,我似乎不再崩溃:

我现在唯一的评论是我希望色块在单元格中仍然可见。但是当我单击下拉箭头时,我只会看到颜色块。这是一个单独的问题吗?

【问题讨论】:

    标签: c# winforms datagridview exception-handling datagridviewcomboboxcell


    【解决方案1】:

    DataGridView 无法解析选定的颜色项。我建议您将自定义解析逻辑应用于该列:

    DataGridView1.CellParsing += ColorCellParsing;
    
    private void ColorCellParsing(object sender, DataGridViewCellParsingEventArgs e)
    {
        var grid = (DataGridView)sender;
        var column = grid.Columns[e.ColumnIndex] as DataGridViewComboBoxColumn;
        if (column == null || column.Name != "Color")
            return;
        foreach (ComboboxColorItem item in column.Items)
        {
            if (item.Name == (string) e.Value)
            {
                e.Value = item;
                e.ParsingApplied = true;
                break;
            }    
        }
    }
    

    【讨论】:

    • 谢谢。这似乎也不起作用。起初我认为它有帮助。
    • 我注意到在您的示例和我的调试中,我们只是查看文本值。但我们也有实际的 Color 对象。我们如何解析它?
    • @AndrewTruckle,颜色名称是 e.Value 返回(由于 ToString() 实现)。但可以更改列 cboColumn.ValueMember = "Index"; 的 ValueMember
    • 现在好了。 ? 我更新了这个问题,但我认为我应该接受这个并做一个新的。
    • @AndrewTruckle,看看这里:stackoverflow.com/questions/7482534/…
    【解决方案2】:

    当你想要获取字符串以外的东西时,将列的ValueType设置为typeof(&lt;data type&gt;)
    例如,如果它是 int

    this.gridViewSettings.Columns("columnName").ValueType= typeof(Int32);
    

    this.ComboboxCellcolumnName.ValueType = typeof(int);
    

    【讨论】:

    • 谢谢。我刚刚尝试击中星星并得到同样的错误。
    • 谢谢。 cboColumn.ValueType = typeof(Color);cboColumn.ValueType = typeof(ComboboxColorItem); 我都试过了,似乎没什么区别。 :(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多