Laden...

DataGridView: Zellen als ComboBox

Erstellt von Binärathlet vor 13 Jahren Letzter Beitrag vor 13 Jahren 27.177 Views
Thema geschlossen
B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren
DataGridView: Zellen als ComboBox

Hallo,

ich verzweifel gerade wieder fast an einem Problem, bei dem mir alles, was ich im Nezt finden konnte, nicht wirklich weitergeholfen hat.
Ich habe ein DataGridView mit einer Zeile und n Spalten. In jeder Zelle steht entweder 0, 1 oder -1. Nun möchte ich einfach den Wert der Zelle abfragen und durch eine ComboBox-Zelle ersetzen, die es mir erlaubt, 0, + oder - auszuwählen.
Das Auslesen des Wertes bekomme ich noch gebacken. Aber wie mache ich daraus dann eine ComboBox-Zelle und wie setze ich innerhalb dieser den Index??

Ich hoffe mal, ihr habt eine Idee!?

Y
238 Beiträge seit 2005
vor 13 Jahren

Hi binärathlet,

  • wie sind die Daten and das Grid gebunden? Sind es Collections, DataTables... ?
  • brauchst du eventuell ganze ComboBox-Spalten oder müssen es wirklich einzelne ComboBox-Zellen sein?

Gruß

Y
238 Beiträge seit 2005
vor 13 Jahren

Also ich würde es in etwa so machen:


#region Create and fill the main data table

// Tabelle mit den eigentlichen Daten
DataTable mainData = new DataTable("Main";);
mainData.Columns.Add("FirstName", typeof(string));
mainData.Columns.Add("LastName", typeof(string));

DataRow person1 = mainData.NewRow();
person1["FirstName"] = "Joe";
person1["LastName"] = "Satriani";

DataRow person2 = mainData.NewRow();
person2["FirstName"] = "Juergen";
person2["LastName"] = "Drews";

mainData.Rows.Add(person1);
mainData.Rows.Add(person2);
mainData.AcceptChanges();

#endregion Create and fill the main data table

#region Create and fill additional data table

// Tabelle mit den Werten fuer die ComboBox
DataTable additionalData = new DataTable("Additional";);
additionalData.Columns.Add("Rating", typeof(string));

DataRow awesomeRating = additionalData.NewRow();
awesomeRating["Rating"] = "Awesome";

DataRow goodRating = additionalData.NewRow();
goodRating["Rating"] = "Good";

DataRow terribleRating = additionalData.NewRow();
terribleRating["Rating"] = "Terrible";

additionalData.Rows.Add(awesomeRating);
additionalData.Rows.Add(goodRating);
additionalData.Rows.Add(terribleRating);
additionalData.AcceptChanges();

#endregion Create and fill the additional table

#region Create and fill dataSet

DataSet dataSet = new DataSet();
dataSet.Tables.Add(mainData);
dataSet.Tables.Add(additionalData);

#endregion Create and fill dataSet

#region Create and fill the ComboBox-Column

DataGridViewComboBoxColumn ratingColumn = new DataGridViewComboBoxColumn();
ratingColumn.Name = "Rating";
ratingColumn.HeaderText = "Rating";
ratingColumn.HeaderCell.Value = "Rating";
ratingColumn.DataPropertyName = "Rating";
ratingColumn.DataSource = dataSet.Tables["Additional"];
ratingColumn.ValueMember = dataSet.Tables["Additional"].Columns["Rating"].ColumnName;
ratingColumn.DisplayMember = dataSet.Tables["Additional"].Columns["Rating"].ColumnName;

#endregion Create and fill the ComboBox-Column

#region Bind data to the grid and attach a comboBoxColumn

this.dataGridView.DataSource = dataSet;
this.dataGridView.DataMember = dataSet.Tables["Main"].TableName;
this.dataGridView.Columns.Add(ratingColumn);
this.dataGridView.ReadOnly = false;

#endregion Bind data to the grid and attach a comboBoxColumn

#region Set custom values for 'Rating' cells

DataGridViewComboBoxCell person1ComboBoxCell = (this.dataGridView.Rows[0].Cells["Rating"] as DataGridViewComboBoxCell);
person1ComboBoxCell.Value = ((DataTable)person1ComboBoxCell.DataSource).Rows[0]["Rating"];

DataGridViewComboBoxCell person2ComboBoxCell = (this.dataGridView.Rows[1].Cells["Rating"] as DataGridViewComboBoxCell);
person2ComboBoxCell.Value = ((DataTable)person1ComboBoxCell.DataSource).Rows[2]["Rating"];

#endregion Set custom values for 'Rating' cells

18 Beiträge seit 2010
vor 13 Jahren
            
if (extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
{
     if (extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "Yes" || extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "No")
      {
                    // ------------------------------------------------
                    // Create an new ComboBoxCell         
                    DataGridViewComboBoxCell cbo1 = new DataGridViewComboBoxCell();
                    // Add Items to the ComboBox
                    cbo1.Items.Add("Yes");
                    cbo1.Items.Add("No");
                    // Set the displayed value.
                    // This value needs to be present
                    // in the items collection
                    cbo1.Value = (extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "No" ? cbo1.Items[1] : cbo1.Items[0]);
                    cbo1.FlatStyle = FlatStyle.Standard;
                    cbo1.MaxDropDownItems = 3;
                    // Save the CurrentCell
                    curCell = extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
                    // Set the Value into the DGVCell
                    extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
                    // DataGridViewCell = DataGridViewComboBoxCell
                    extDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] = cbo1;

                }

Vielleicht hilft dir das ne Stück weiter

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

Hallo recmar,

danke, genau sowas hab ich gesucht. Allerdings funktioniert meine Interpretation deines Vorschlages noch nicht wirklich, da ständig das DataError-Ereignis abgefeuert wird und die ComboBox schließlich nicht angezeigt wird !?
Hier der Code dazu:


// Spalten durchlaufen
                for (int i = 0; i < objInstance.grdDataGrid.Rows.Count; i++)
                {
                    // Zeilen durchlaufen
                    for (int j = 1; j < objInstance.grdDataGrid.Columns.Count; j++)
                    {
                        if (objInstance.grdDataGrid.Rows[i].Cells[j].Value != null)
                        {
                            // ComboBox - Zelle anlegen
                            DataGridViewComboBoxCell vComboCell = new DataGridViewComboBoxCell();
                            vComboCell.Items.AddRange(new object[3] {"++", "o", "--"});

                            // Index auswählen
                            if (objInstance.grdDataGrid.Rows[i].Cells[j].Value.ToString() == Convert.ToString(1))
                                vComboCell.Value = vComboCell.Items[0];
                            else if (objInstance.grdDataGrid.Rows[i].Cells[j].Value.ToString() == Convert.ToString(-1))
                                vComboCell.Value = vComboCell.Items[2];
                            else
                                vComboCell.Value = vComboCell.Items[1];

                            // Anzeige festlegen
                            vComboCell.FlatStyle = FlatStyle.Standard;
                            vComboCell.MaxDropDownItems = 3;

                            // Datentyp festlegen
                            objInstance.grdDataGrid.Rows[i].Cells[j].Value = objInstance.grdDataGrid.Rows[i].Cells[j].Value.ToString();
                            
                            // ComboBox - Zelle setzen
                            objInstance.grdDataGrid.Rows[i].Cells[j] = vComboCell;
                        }
                    }
                }

5.299 Beiträge seit 2008
vor 13 Jahren

Der frühe Apfel fängt den Wurm.

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

Hallo ErfinderDesRades,

danke für den Code, aber langsam glaube ich wirklich, ich bin zu dämlich, das zu kapieren. In dieser (in Anlehnung an deinen Code) gehaltenen Version laufe ich erstens in eine ArgumtentException und zweitens habe ich immernoch nicht verstanden, wozu ich die BindingSource brauche bzw. wie es ohne ginge ....


BindingSource vSource2 = new BindingSource();
vSource2.Add(new object[3] { "++", "o", "--" });
DataGrid.DataSource = vSource2;
DataGrid.AutoGenerateColumns = false;
DataGrid.AutoSize = true;

for (int i = 1; i < 10; i++)
{
             DataGrid.Columns.Add(CreateComboBox("TEST"));
}

private DataGridViewComboBoxColumn CreateComboBox(string vTitle)
{
            DataGridViewComboBoxColumn vCombo = new DataGridViewComboBoxColumn();
            vCombo.DataSource = Enum.GetValues(typeof(String)); // --> ArgumentException
            vCombo.DataPropertyName = vTitle;
            vCombo.Name = vTitle;
            return vCombo;
}

5.299 Beiträge seit 2008
vor 13 Jahren

schau dir nochmal genau an, welchen Typ ich bei Enum.GetValues() übergebe.

Der frühe Apfel fängt den Wurm.

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

aha .... jetzt funzts, danke fürs 'Nase-auf-die-Lösung-drücken' 😁
wenn du mir jetzt noch sagen könntest, wie ich den Index festlege, wäre ich vollends glücklich ...


DataGrid.Columns.Clear();
DataGrid.AutoGenerateColumns = false;
DataGrid.AutoSize = true;

for (int i = 1; i < 10; i++)
{
    objInstance.grdDataGrid.Columns.Add(CreateComboBox("TEST"));
}

private DataGridViewComboBoxColumn CreateComboBox(string vTitle)
 {
      DataGridViewComboBoxColumn vCombo = new DataGridViewComboBoxColumn();
      vCombo.DataSource = new object[4] { "HUND", "KATZE", "MAUS", "OTZELOT" };
      vCombo.DataPropertyName = vTitle;
      vCombo.Name = vTitle;
      return vCombo;
  }

Y
238 Beiträge seit 2005
vor 13 Jahren

Hallo Binärathlet,

wenn du mir jetzt noch sagen könntest, wie ich den Index festlege

dir wurden drei Lösungsvorschläge (fast schon Musterlösungen) presentiert und die Antwort auf deine Frage ist defenitiv dabei... Du musst dich jetzt auch mal anstrengen!

😄

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

gut, die DataGridViewComboBoxCell kenn ich jetzt in- und auswendig und kann sogar den Index setzen 😁 ... aber bei der DataGridViewComboBoxColumn krieg ich es ums Verrecken nicht hin. Keine Ahnung was ich falsch mach, aber ich bekomm es nicht gebacken 8o 8o

54 Beiträge seit 2010
vor 13 Jahren

Naja vCombo.Index ist Read-Only. Hast dus mal mit vCombo.DisplayIndex probiert? Naja das wird dir vermutlich nicht viel helfen, da es ja nur die angezeigte Reihenfolge beeinfluss.

Wozu willst du den Index der Column eigentlich selbst bestimmen?

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

DisplayIndex bringt auch nichts. Ich will doch nur festlegen, was in diesem DropDown-Element ausgewählt erscheint, wenn man es öffnet, das muss doch möglich sein oder!?
Aber es gibt ja scheinbar auch nicht wirklich eine Möglichkeit, die Zellen der DataGridViewComboBoxColumn zu durchlaufen und in der jeweiligen Celle den Index zu setzen!?

F
10.010 Beiträge seit 2004
vor 13 Jahren

Naja, das macht doch der gebundene Wert.

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

scheinbar bin ich der Einzige, ders nicht kapiert 🤔



// Spalte hinzufügen
DataGridView.Columns.Add(mCreateComboBox(vGridData.Columns[i].ColumnName);

// Spalte generieren
private DataGridViewComboBoxColumn mCreateComboBox(string vTitle)
        {
            DataGridViewComboBoxColumn vCombo = new DataGridViewComboBoxColumn();
            vCombo.DataSource = new object[3] { "ja", "nein", "vielleicht" };
            vCombo.DataPropertyName = vTitle;
            vCombo.Name = vTitle;
            vCombo.MaxDropDownItems = 3;
            vCombo.FlatStyle = FlatStyle.System;


54 Beiträge seit 2010
vor 13 Jahren

int i,j = 0; //Zeile und Spalte 
datagridview1.Rows[i].Cells[j].Value = "ja";
//oder
//datagridview1.Rows[i].Cells[j].Value = "nein";
//oder
//datagridview1.Rows[i].Cells[j].Value = "vielleicht";

je nachdem was du eben willst und wohin es soll. Wenn du es über einen Index haben willst wirst du wohl den Weg über Enums von ErfinderDesRades nehmen müssen.

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

Wenn das so funktionieren würde, würde es mir schon reichen, aber leider scheint das nicht zu gehen:


// Spalte hinzufügen
DataGridView.Columns.Add(mCreateComboBox(vGridData.Columns[i].ColumnName);

// Index setzen (erste Spalte, erste Zeile)
DataGridView.Rows[0].Cells[0].Value = "nein";


// Spalte generieren
private DataGridViewComboBoxColumn mCreateComboBox(string vTitle)
{
            DataGridViewComboBoxColumn vCombo = new DataGridViewComboBoxColumn();
            vCombo.DataSource = new object[3] { "ja", "nein", "vielleicht" };
            vCombo.DataPropertyName = vTitle;
            vCombo.Name = vTitle;
            vCombo.MaxDropDownItems = 3;
            vCombo.FlatStyle = FlatStyle.System;
}

Die Werte sind zwar in der Zelle hinterlegt, nur sieht das ganze trotz Setzen des Indexes so aus:

54 Beiträge seit 2010
vor 13 Jahren

Das ist merkwürdig. Bei mir gehts. Es ist nicht zufällig die ForeColor gleich der BackColor? Nur um das einfachste mal auszuschließen. 😁
Bzw. ist das angelegte auch Cells[0]? Keine anderen Columns davor?

Funktioniert das Dropdownmenü beim drauf drücken? Die 3 Einträge sollten ja angezeigt werden?

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

loool, jetzt habe ich mir das ganze nochmal in einem primitiven Beispiel nachgebaut und auch da gehts. Scheinbar liegt dann das Problem irgendwo im restlichen Code. Naja, dann weiß ich jetzt zumindest, dass ich an der falschen Stelle suche 😁

Jedenfalls danke für deine Geduld !! 👍 👍

B
Binärathlet Themenstarter:in
26 Beiträge seit 2010
vor 13 Jahren

Also dieses Ding schafft mich noch. Jetzt funktioniert endlich die Auswahl des Indexes, wenn ich nun aber dem Nutzer verbiete, Zeilen hinzuzufügen oder zu löschen, enthält das DataGridView auf einmal gar keine Einträge mehr


 public partial class GridForm : Form
    {
        public GridForm()
        {
            InitializeComponent();

            this.gridView.Columns.Clear();
            this.gridView.AutoGenerateColumns = false;
            this.gridView.AutoSize = false;

            for (int i = 0; i <= 10; i++)
            {
                gridView.Columns.Add(mCreateComboBox("TEST"));
            }

            for (int i = 0; i <= 10; i++)
            {
                if (i % 2 == 0)
                    gridView.Rows[0].Cells[i].Value = "nein";
                else
                    gridView.Rows[0].Cells[i].Value = "vielleicht";
            }

            // --> Diese zwei Zeilen führen dazu, dass die DataGridView überhauptkeine Spalten und Zeilen mehr enthält
            this.gridView.AllowUserToAddRows = false;
            this.gridView.AllowUserToDeleteRows = false;

        }

        private DataGridViewComboBoxColumn mCreateComboBox(string vTitle)
        {
            // ComboBox initialisieren
            DataGridViewComboBoxColumn vCombo = new DataGridViewComboBoxColumn();
            vCombo.DataSource = new object[3] { "ja", "nein", "vielleicht" };
            vCombo.DataPropertyName = vTitle;
            vCombo.Name = vTitle;
            vCombo.MaxDropDownItems = 3;
            vCombo.FlatStyle = FlatStyle.System;

            return vCombo;
        }
    }

54 Beiträge seit 2010
vor 13 Jahren

Lass mich raten. Vorher hattest du genau eine Zeile?
Du musst natürlich alle Zeilen dann vom Programm erzeugen lassen. Also

this.gridView.Rows.Add()
F
10.010 Beiträge seit 2004
vor 13 Jahren

@Binärathlet:
Welchen Teil von gebundenen Wert hast du nicht verstanden?
Anscheinend den gesamten Satz.

Du sollst die Daten nicht ins Grid frickeln, sondern die Daten Binden ( DataTable?! )
DataGridView.AllowUserToAddRows-Eigenschaft
Und hier siehst du unter Hinweis das es eine Eigenschaft ist, die bei gebundenen Daten benutzt wird.

Y
238 Beiträge seit 2005
vor 13 Jahren

@Binärathlet,

wenn ich nun aber dem Nutzer verbiete, Zeilen hinzuzufügen oder zu löschen, enthält das DataGridView auf einmal gar keine Einträge mehr

für das Grid ist es das gleiche als hättest du es implicit auf "ReadOnly" gesetzt, vermutlich bleben die ComboBoxen deswegen leer.

BITTE, BITTE, BITTE schaue dir doch ENDLICH die Lösungsvorschläge an die dir Community gibt !!! ErfinderDesRades, recmar, und meine wenigkeit hatten dir schon vor 2 Wochen funktionierende Beispiele angeboten (sogar mit Databinding und Indexsetzen) !!! Auch FZelle gibt dir einen sehr wertvollen Tipp

Du sollst die Daten nicht ins Grid frickeln, sondern die Daten Binden ( DataTable?! )

Einfach nur systematisch die gegebene Info durcharbeiten...

Hinweis von gfoidl vor 13 Jahren

Passendes Schlusswort von yngwie. Alle nötigen Infos wurde mehrfach genannt.

Thema geschlossen