Hallo,
suche leider vergebens nach einem vernünftigen Ansatz für oben genanntes Problem. Eine DataGridViewComboBoxColumn soll z.B. rot markierte Einträge enthalten, wenn eine andere Spalte im Dataset (Datenquelle) true/false ist.
Das Problem ist wohl eher die Anzeige beim aufklappen der Combobox-Spalte, dass da dann die markierten Items auch wie gewünscht angezeigt werden. Hat jemand eine Idee?
:::
Hallo diana,
das wird wohl nur mit einer OwnerDrawn-ComBobox gehen. Ob DataGridViewComboBoxen OwnerDrawn sein können, weiß ich allerdings nicht.
herbivore
OwnerDraw? Ich hatte auch schon nach Draw-Events für diese Column gesucht, aber nix. Muss ich dann für diese Spalte ein anderes Coltrol verwenden? Wenn ja welchen "Combobox"-Typen?
:::
Du kannst das OnCellPaint vom DGV verwenden um selbst zu Zeichnen oder einfach die DGVComboBoxColumn & DGVComboBoxCell ableiten und das Paint überschreiben
public class MyDataGridViewColumn: DataGridViewComboBoxColumn
{
public override DataGridViewCell CellTemplate
{
get { return new MyDataGridViewCell(); }
}
}
public class MyDataGridViewCell : DataGridViewComboBoxCell
{
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
.....
}
}
EDIT: geht bei einer ComboBox nicht wie gewünscht (siehe unten)
Bei der Combobox läuft das wohl anders habs gerade ausprobiert.
Das hier könte helfen
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if(e.Control is ComboBox)
((ComboBox)e.Control).DrawItem += new DrawItemEventHandler(Form1_DrawItem);
}
void Form1_DrawItem(object sender, DrawItemEventArgs e)
{
}
Achso, ich verwende aber eine DataGridViewComboBoxColumn und die besitzt leider kein Draw-Event:?
:::
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
So nach dem ich mir die Beispiele etwas näher angeschaut habe, weiß ich auch wo ich ca. hin will. Eigentlich zum DrawItem-Event der DatagridViewComboboxColumn, aber das gibt es leider nicht. Diese Möglichkeit bietet nur die Combobox selbst. Also ein eigenes Control mit den Klassen DataGridViewComboboxColumn : DataGridViewColoumn, Combobox : DataGridViewComboboxCell und ComboboxEditingControl: Combobox , IDataGridViewEditingControl
aufsetzen und die Eigenschaft DrawMode und das Event DrawItem der Combobox der
DataGridViewComboboxColumn durchreichen? Leider weiß ich eben nicht genau, ob mein Lösungsansatz überhaupt Sinn macht und ich so auch wirklich irgendwann an die Forecolor des einzelnen Items rankomme? Oder gibt es eine einfachere Lösung?
:::
Hat vielleicht jemand noch eine Idee, ob ich auf der richtigen Fährte bin oder wie würdet ihr das realisieren?
:::
Hallo diana,
da es doch einige Klassen, Interfaces, Beziehungen und Unbekannte im Spiel sind, wird das wohl kaum jemand nur nach deiner Beschreibung bestätigen können. Man müsste es ausprobieren. Das kannst und solltest du jedoch am besten selber machen. Wenn Probleme konkrete damit auftauchen, die du genau beschreibst, ist es vermutlich wieder einfacher zu helfen.
herbivore
Ich habe es vorerst noch mal mit dem EditingControlShowing-Event des DataGridView versucht:
private void dgrv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
((ComboBox)e.Control).DrawMode = DrawMode.OwnerDrawFixed;
((ComboBox)e.Control).DrawItem += new DrawItemEventHandler(Frm_DrawItem);
}
private void Frm_DrawItem(object sender, DrawItemEventArgs e)
{
ComboBox cbo = (ComboBox)sender;
int yPostition = (e.Index - cbo.Top) * cbo.ItemHeight + 100;
e.Graphics.DrawString(ds.dt[0]["ANZEIGE_NAME"].ToString(), cbo.Font, new SolidBrush(Color.Blue), 0.0f, yPostition);
}
Kurz: Ich würde gern bestimmte Items in der DataGridViewComboBox farbig hervor heben! Nach dem obigen ersten wackligen Testcode, bekomme ich zwar farbige Einträge, aber irgentwo im Control und meine Datenbankeinträge aus meinem ds, weiß ich leider auch noch nicht, wie ich die reinbringe, da dieses DrawItem-Event immer ausgeführt wird, wenn ich mit der Mouse drauf binim ausgeklappten Zustand. Vielleicht traut sich jemand ran...:/
Wichtig ist auch erstmal wie zeichne ich die Items, die aus dem DataSet kommen, hab es schon auf die herkömmliche versucht, hat nicht funktioniert.
:::
Du hast ja den Text sowieso in deiner ComboBox (weil du ja deine daten darauf gemappt hast)
string text = ((ComboBox)sender).Items[e.Index].ToString();
Dann fragst du deine Bedingungen ab,
if(text.Contains("whatever"))
myBrush = Brushes.Purple;
und am ende Zeichnest du das ganze noch
e.DrawBackground();
e.Graphics.DrawString(text, ((Control)sender).Font, myBrush, e.Bounds.X, e.Bounds.Y);
Vielen Dank für deine Antwort. Gemappt heit sicherlich an eine Datenspalte gehangen, dass habe ich per:
this.col = new DataGridViewComboBoxColumn();
this.col.DataSource = ds.Tables["Name"].DefaultView;
this.col.DataPropertyName = "NR";
this.col.ValueMember = "NR";
this.col.DisplayMember = "ANZEIGE_NR";
realisiert, aber sobald ich das DrawItem-Event verwende, wir kein Eintrag als Textitem in der Combobox angezeigt. Während der Laufzeit ist text auch leider null, also hat die Combobox die Daten doch noch nicht oder nicht mehr, obwohl, was etwas verwundert, die Länge der Count auf die Items stimmt nur der text wird eben nicht abgezeigt:/
:::
Natürlich wird der Text nicht angezeigt weil du ihn selbst zeichnen musst wenn du das DrawItem Event überschreibst 😉
Ich dachte text = ((ComboBox)sender).Items[e.Index].ToString(); hat die einzelnen Items!
Also brauche ich eine solche benutzerdefinierte Combobox? Leider wurde auch nicht beschrieben, wo ich das Add der Items vornehme, im DrawItem? oder vorher?
Habe mal versucht im DrawItem mein ds per Foreach duchzugehen und dann die Einträge per Add zu setzen, da zeigt mir die ComboBox leider nur System.Data-DataRowView an. (Habe den Code zum Test schnell kopiert)
e.DrawBackground();
Brush brush;
// Get the item text.
try
{
foreach (DataRow dr in ds.dt.Rows)
{
((ComboBox)sender).Items.Add(dr["ANZEIGE_NAME"].ToString());
}
}
catch { }
string text = ((ComboBox)sender).Items[e.Index].ToString();
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
brush = Brushes.Yellow;
}
else
{
brush = Brushes.Red;
}
// Draw the text.
e.Graphics.DrawString(text, ((Control)sender).Font, brush, e.Bounds.X, e.Bounds.Y);
Leider sehe ich immer noch nicht so richtig durch, was noch fehlt:/
:::
Also du Lädst ja Irgendwo dein DataSet, dannach solltest du deine ComboBox Items auffüllen, (nicht im Interface / sonst hast du in einer InterfaceMethode einen zugriff auf BackgroundDaten was nicht schön ist)
also nachdem dein DataSet Complet ist füllst du deine CombBox
((ComboBox)sender).Items.Add(dr["ANZEIGE_NAME"].ToString())
was du hier machst ist denke ich falsch weil du deine Items mit DataRows auffüllst und nicht mit DataCells (das ToString auf eine DataRow gibt nur den KlassenNamen)
((ComboBox)sender).Items.Add(dr["ANZEIGE_NAME"].Cells[0].ToString())
Würde dir zum Beispiel den wert in der ersten Spalte geben.
EDIT: Stimmt war falsch aber wie man mit einem DataSet arbeitet findest du bestimmt selbst raus.
In deiner DrawItem Methode solltest du dann wieder die Items verwenden so wie es im link Oben auch gemacht wurde.
.Cells wird in diesem Zusammenhang gar nicht angeboten...
Wie man mit einem DataSet arbeitet ist nicht das Problem, sondern das Arbeiten mit einer DataGridViewComboBoxColumn...:/
:::
Daten werden nun aus dem Dataset in die DataGridViewComboBoxColumn geladen, nur leider bringt:
((ComboBox)sender).Items[e.Index].ToString();
im DrawItem immer -1 als Index, sodass kein Item in der DataGridViewComboBoxColumn angezeigt wird. Ich habe es mal mit 0 ausprobiert, da kommt mein erster Eintrag korrekt.
Nun also die nächste Frage, wie komme ich an einen e.Index, sodass mein DrawIndex-Event die Einträge ordentlich anzeigen kann? Momentan siehts so aus, dass ich nur statisch den Index setzen kann z.B. 0 und so wird mein erster Eintrag soviel mal wie Items.Count angezeigt, was ja logisch ist:/ Ich brauche also den "dynamischen Index"?
:::
Guten Morgen,
leider bin ich noch zu keiner weiteren Erkenntnis gekommen, warum e.Index im DrawItem immernoch -1 ist. Habe schon einige Einstellungen verändert, DrawMode, DropDownStyle nichts passiert, obwohl die DataGridViewComboBoxColumn die Daten ja schon hat... Hat jemand noch eine Idee?
:::
EDIT:
Ich glaube -1 steht für den Header?
Frag einfach auf -1 ab und mach in dem Fall nichts.
Hab ein dummy Projekt erstellt:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
((ComboBox)e.Control).DrawMode = DrawMode.OwnerDrawFixed;
((ComboBox)e.Control).DrawItem += new DrawItemEventHandler(Form1_DrawItem);
}
void Form1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index == -1)
return;
e.DrawBackground();
Brush brush;
string text = ((ComboBox)sender).Items[e.Index].ToString();
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
brush = Brushes.Yellow;
}
else
{
if (text.Contains("special"))
brush = Brushes.Red;
else
brush = Brushes.Black;
}
e.Graphics.DrawString(text, ((Control)sender).Font, brush, e.Bounds.X, e.Bounds.Y);
}
private void Form1_Load(object sender, EventArgs e)
{
((DataGridViewComboBoxColumn)this.dataGridView1.Columns[0]).Items.AddRange(new string[] { "test", "special", "test", "test", "test", "test" });
}
}
Nichts für ungut, aber das hat mich ca 5 Minuten gekostet um das auszuprobieren und es funktioniert, mehr eigeninitiative beim nächsten mal
if (e.Index == -1) return;
Hatte gefehlt, ansonsten sieht mein Code genauso aus wie deiner, dass hier natürlich im Header angefangen wird mit zählen, muss man erst wissen, sodass man das abfängt und es dann fröhlich weiter geht. Vielen vielen Dank. Sorry, aber man weiß eben einfach nicht mehr wo man noch suchen soll! Funktioniert alles prima:)
:::