创建一个DataGridView,它具有DataGridViewComboBoxColumn类型的第二列,单元格值为ComboboxColorItem,使用我的DataSource

时间:2016-06-07 08:52:08

标签: c# xml datagridview

我决定重新提出这个问题。这就是......

我有一个XML文件:

<?xml version="1.0" standalone="yes"?>
<GenioCodes>
  <Code Layer="BI" Colour="1" />
  <Code Layer="BP" Colour="1" />
  <Code Layer="BS" Colour="1" />
  <Code Layer="C" Colour="1" />
  <Code Layer="CC" Colour="1" />
  <Code Layer="CR" Colour="1" />
</GenioCodes>

我将其读入DataSet并在DataSource对象上将其设为DataGridView

m_dataSet.ReadXml(textBoxXML.Text);
m_dataGridView.DataSource = m_dataSet.Tables[0];

DataGridView需要有两列:

第1列:这是默认的string列,应绑定到图层属性。

第2列:这必须是DataGridViewComboBoxColumn列,并且应该绑定到颜色属性。

第2列单元格对象必须是ComboboxColorItem类型。类:

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

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

    static public ComboboxColorItem Create(ushort iColourIndex)
    {
        OdCmColor oColour = new OdCmColor();

        oColour.setColorIndex(iColourIndex);

        ComboboxColorItem oColorItem = new ComboboxColorItem(
            oColour.colorNameForDisplay(),
            iColourIndex,
            Color.FromArgb(oColour.red(), oColour.green(), oColour.blue()));

        oColour.Dispose();

        return oColorItem;
    }
}

因此,正如您所看到的,XML中的Color属性只是一个数字。但我们可以使用静态ComboboxColorItem.Create方法从中创建一个单元格项。

如何将这些全部放在一起?如何使用我的ComboboxColorItem创建一个DataGridView,它具有类型为DataGridViewComboBoxColumn的第二列,其单元格值为DataSource

注意:如果需要,我可以更改XML文件的结构。

3 个答案:

答案 0 :(得分:1)

根据您的问题,我创建了一个使用DataSet的工作考试。 IMO,在ComboBox列中使用原始类型更简单。

GetColorFromCode应使用OdCmColor为ComboBox项创建颜色和文本。我无法访问该课程。

此示例缺少自定义单元格绘制

public partial class DgvForm : Form
{
    private string xml = 
@"<?xml version='1.0' standalone='yes'?>
<GenioCodes>
  <Code Layer='BI' Colour='1' Value='qwerty'/>
  <Code Layer='BP' Colour='2' />
  <Code Layer='BS' Colour='3' Value='Hello'/>
  <Code Layer='C' Colour='4' />
  <Code Layer='CC' Colour='1' />
  <Code Layer='CR' Colour='1' />
</GenioCodes>";

    DataSet m_dataSet = new DataSet();

    public DgvForm()
    {
        InitializeComponent();

        // reading xml from string
        var reader = XmlReader.Create(new StringReader(xml));            
        m_dataSet.ReadXml(reader);
        m_dataGridView.DataSource = m_dataSet.Tables[0];

        var column = m_dataGridView.Columns["Colour"];
        int idx = column.Index;
        // removing text column
        m_dataGridView.Columns.RemoveAt(idx);

        // adding comboBox column
        var cbo = new DataGridViewComboBoxColumn
        {
            Name = "Colour",
            DataPropertyName = "Colour",
        };
        // unique color codes for comboBox
        var colorCodes = m_dataSet.Tables[0].AsEnumerable()
                    .Select(r => r["Colour"])
                    .Distinct()
                    .ToList();
        cbo.DataSource = colorCodes;
        // restore column in orignal position
        m_dataGridView.Columns.Insert(idx, cbo);

        m_dataGridView.EditingControlShowing += ComboBoxShowing;
    }
    /// <summary>
    /// Activates custom drawing in comboBoxes
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ComboBoxShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {            
        if (e.Control is ComboBox)
        {
            ComboBox theCB = (ComboBox)e.Control;
            theCB.DrawMode = DrawMode.OwnerDrawFixed;
            try
            {
                theCB.DrawItem -= new DrawItemEventHandler(this.ComboItemDraw);
            }
            catch { }
            theCB.DrawItem += new DrawItemEventHandler(this.ComboItemDraw);
        }
    }

    /// <summary>
    /// Custom drawing for comboBox items
    /// </summary>
    private void ComboItemDraw(object sender, DrawItemEventArgs e)
    {
        Graphics g = e.Graphics;

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

        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)
        {
            g.FillRectangle(Brushes.LightBlue, rDraw);
            g.DrawRectangle(Pens.Blue, rDraw);
        }
        else
        {
            g.FillRectangle(Brushes.White, e.Bounds);
        }


        if (e.Index < 0)
            return;
        string code = ((ComboBox) sender).Items[e.Index].ToString();

        Color c = GetColorFromCode(code);
        string s = c.ToString();

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

    /// <summary>
    /// Returns color for a given code 
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    private Color GetColorFromCode(string code)
    {
        switch (code)
        {
            case "1": return Color.Green;
            case "2": return Color.Cyan;
            case "3": return Color.Orange;
            case "4": return Color.Gray;
        }
        return Color.Red;
    }
}

答案 1 :(得分:0)

尝试遍历每个数据集,然后使用.Rows.Add函数将其绑定到Datagridview ...

        //Creates and Adds Rows for all Data
        for (int i = 0; i < DataSet.Count; i++)
        {
            DataGridView.Rows.Add(new object[] { columnArray1[i], columnArray2[i] });
        }

答案 2 :(得分:0)

感谢您提供迄今为止提供的答案,我非常感谢他们。

我理解它的方式,您可以将DataGridView属性AutoGenerateColumns设置为false。此属性未在IDE中公开,但可以在代码中使用。

如果该属性设置为 false ,我了解我们可以自行设置DVG列定义,然后只使用DataSet / DataSource组合。所以我希望避免读取数据,然后再次有效地读取数据列(根据当前的答案)。

目前,我已将我的代码简化为手动执行操作。因此:

步骤1 - 初始化DVG:

private void GENIO_Code_Editor_Load(object sender, EventArgs e)
{
    try
    {
        buttonDetect.Enabled = m_dbDatabase != null;

        InitColourComboBoxColumn();

        dataGridView.Columns.Add("Layer", "Layer");
        dataGridView.Columns.Add(cboColumn);

        if (textBoxXML.Text != "")
            ReadXmlToGrid();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

第2步: - InitColourComboBoxColumn方法:

private void InitColourComboBoxColumn()
{
    try
    {
        cboColumn = new DataGridViewComboBoxColumn();
        cboColumn.Name = "Colour";
        cboColumn.ValueMember = "Name";

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

        foreach (ushort iColourIndex in listColours)
            cboColumn.Items.Add(ComboboxColourItem.Create(iColourIndex));
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

步骤3:实现Read / Save to XML方法:

private void ReadXmlToGrid()
{
    try
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(textBoxXML.Text);
        XmlNodeList listCodes = doc.SelectNodes("GenioCodes/Code");

        foreach (XmlNode oCode in listCodes)
        {
            int iRow = dataGridView.Rows.Add();

            dataGridView.Rows[iRow].Cells["Layer"].Value = oCode.Attributes["Layer"].Value;

            ushort iColourIndex = Convert.ToUInt16(oCode.Attributes["Colour"].Value);
            ComboboxColourItem ocbItem2 = null;
            foreach (ComboboxColourItem ocbItem in cboColumn.Items)
            {
                if (ocbItem.Index == iColourIndex)
                {
                    ocbItem2 = ocbItem;
                    break;
                }
            }
            if (ocbItem2 == null)
            {
                ocbItem2 = ComboboxColourItem.Create(iColourIndex);
                cboColumn.Items.Add(ocbItem2);
            }
            dataGridView.Rows[iRow].Cells["Colour"].Value = ocbItem2;
        }
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

private void SaveGridToXml()
{
    XmlDocument doc = new XmlDocument();
    XmlElement codes = doc.CreateElement("GenioCodes");

    foreach(DataGridViewRow row in dataGridView.Rows)
    {
        if(row != null && !row.IsNewRow)
        {
            XmlElement code = doc.CreateElement("Code");
            code.SetAttribute("Layer", row.Cells["Layer"].Value.ToString());

            String strThisColour = row.Cells["Colour"].Value.ToString();
            bool bColourFound = false;
            foreach (ComboboxColourItem ocbItem in cboColumn.Items)
            {
                if (ocbItem.Name == strThisColour)
                {
                    code.SetAttribute("Colour", ocbItem.Index.ToString());
                    bColourFound = true;
                    break;
                }
            }
            if(!bColourFound) // This should not happen
                code.SetAttribute("Colour", "1"); // 1 is red

            codes.AppendChild(code);
        }
    }
    doc.AppendChild(codes);
    doc.Save(textBoxXML.Text);
}

就是这样。它按我的需要工作。如果有替代方案我可以做:

m_DataSet.ReadXml("myfile.xml");
m_DataGridView.DataSource = m_DataSource;
m_DataSet.WriteXml("myfile.xml");

它创建了我想要的DVG类型(没有重新读取任何列或删除)然后我在其他答案中很有趣,因为我认为这只是我的问题的解决方法。