2016-06-07 4 views
0

Ich habe mich entschieden, diese Frage neu zu formulieren. Hier geht ...Erstellen Sie eine DataGridView mit der zweiten Spalte vom Typ DataGridViewComboBoxColumn mit Zellenwerten vom Typ ComboboxColorItem, die meine DataSource verwendet

Ich habe eine XML-Datei:

<?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> 

ich es in ein DataSet lesen und setzen es als DataSource auf dem DataGridView Objekt:

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

Die Datagridview muss haben zwei Spalten:

Spalte 1: Dies ist eine Standardeinstellung string Spalte und sollte an das Layer Attribut gebunden werden.

Spalte 2: Dies muss eine DataGridViewComboBoxColumn Säule sein und sollte auf die Farbe Attribut gebunden werden.

Die Zelle Objekte für Spalte 2 müssen vom Typ .Die Klasse sein:

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

So, wie Sie sehen können, die Farbe Attribut in der XML ist nur eine Zahl. Aber wir können mit der statischen Methode ComboboxColorItem.Create ein Zellenelement erstellen.

Wie lege ich das alles zusammen? Wie kann ich ein DataGridView erstellen, das die zweite Spalte vom Typ DataGridViewComboBoxColumn mit Zellenwerten des Typs unter Verwendung meines DataSource?

Hinweis: Ich kann die Struktur der XML-Datei bei Bedarf ändern.

Antwort

0

Versuchen Sie, durch jeden Datensatz iteriert dann binden sie an die Datagridview die .Rows.Add Funktion ...

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

Willst du sagen, dass ich mein 'm_dataSet.Tables [0]' -Objekt iterieren und Zeilen manuell in das Grid einfügen soll? Ich folge nicht ganz. Irgendwann muss ich in der Lage sein, 'SaveXml' wieder aufzurufen, die Sie mit den aktualisierten Daten im Raster sehen. –

+0

Würde das Speichern jeder Spalten-Dateninfo in ein separates Array funktionieren? Sie können Ihre Datenfelder aus der Datagrid-Ansicht bearbeiten, indem Sie Zeilen mit dem columnArray [datagridview.SelectedRows [0] .Index] auswählen und dann manuell zu den Zeilen hinzufügen, indem Sie den obigen Code verwenden. – iato

+0

Wenn Sie SaveXml aufrufen möchten, können Sie Ihre Spaltenarrays benutzen, da Sie diese frei bearbeiten können ... – iato

1

basierend auf Ihre Fragen, die ich habe eine Arbeits examle mit einem Datensatz erstellt. IMO, es ist einfacher, mit dem primitiven Typ in der ComboBox-Spalte zu arbeiten.

GetColorFromCode sollte OdCmColor verwenden, um eine Farbe und einen Text für ComboBox-Elemente zu erstellen. Ich habe keinen Zugang zu dieser Klasse.

dieses Beispiel fehlt benutzerdefinierte Zelle

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

Danke für Ihre ausführliche Antwort. Ich schätze das und es ist sicherlich eine Möglichkeit, das zu tun, was ich brauche. Bitte finden Sie meine eigene Antwort enthalten (das ist wirklich ein Workaround). Aber es gibt eine andere Möglichkeit, Datensätze/Quellen zu verwenden und eine erneute Arbeit mit den Daten zu vermeiden, die mich interessieren. Vielen Dank. –

0

Danke für die Antworten bisher zur Verfügung gestellt, Malerei, die ich schätze sie so.

So wie ich es verstehe, können Sie Ihre DataGridView Eigenschaft AutoGenerateColumns auf false setzen. Diese Eigenschaft ist in der IDE nicht verfügbar, sie ist jedoch in Code verfügbar.

Wenn diese Eigenschaft auf falsch gesetzt ist, verstand ich, dass wir die DVG Spalte selbst Definitionen könnte und dann benutzen Sie einfach eine DataSet/DataSource Kombination. Ich hatte also gehofft, dass ich die Daten nicht einlesen und dann die Datensäule wieder effektiv lesen kann (laut aktueller Antwort).

Vorerst habe ich meinen Code vereinfacht, um Dinge manuell zu tun. Also:

Schritt 1 - Initialisieren der 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()); 
    } 
} 

Schritt 2: - Die InitColourComboBoxColumn Methode:

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

Schritt 3: Implementieren Sie die Read/to XML Methoden speichern:

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

Das ist es. Es funktioniert wie ich brauche. Wenn es eine Alternative, wo das kann ich nur tun:

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

Und die Art der DVG erstelle ich den Wunsch bin (ohne Spalten oder Löschen erneut lesen), dann bin ich interessant in anderen Antworten, wie ich dies unter Berücksichtigung nur eine Problemumgehung für mein Problem.

Verwandte Themen