Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DataGridView

71 views
Skip to first unread message

Marco von Frieling

unread,
Jan 7, 2006, 12:06:05 PM1/7/06
to
Hallo,

ich habe ein paar Fragen zum DataGridView:
1. Ist es möglich eine Fußzeile zu erstellen? Ich meine eine
DataGridViewRow die am unteren Ende des DataGridView fixiert ist, nicht
mitscrollt und auch keinen normalen Datensatz, sondern z. B. die Anzahl
der Datensätze o. ä. anzeigt. Diese Zeile soll immer am unteren Ende des
DataGridView zu sehen sein, sowohl wenn weniger Zeilen als möglich auf
einmal angezeigt werden (oder gar keine) als auch wenn es sehr viele
Zeilen sind. Beispiel siehe [1].
2. Das DataGridView ist unbound und wird komplett im Code aufgebaut.
Dies geht leider nicht anders da alle in [1] zu sehenden, nicht grauen
Spalten sehr dynamisch sind, und zwar in Bezug auf Existenz, Inhalt und
Verhalten. Den anderen Spalten habe ich vor dem Hinzufügen zum
DataGridView konstante Namen zugewiesen. Beim Laden der Daten wollte ich
dann auf die Zellen über diese Namen statt über deren Indizes zugreifen,
das hat jedoch nicht funktioniert:


const string IDColumn = "ID";
void LoadData()
{
DataGridViewRow row = (DataGridViewRow)dgView.RowTemplate.Clone();
row.CreateCells(dgView);
// Startnummer
DataGridViewCell cell = row.Cells[IDColumn]; // Es gibt keine Zelle
mit dem Namen.
// ...
}

Wozu sind dann die Namen da??


[1] http://mvf.gmxhome.de/ExtendedDataGridView.gif

Gruß,
Marco

Frank Dzaebel

unread,
Jan 8, 2006, 5:04:24 AM1/8/06
to
Hallo Marco,

> [DataGridView]


> 1. Ist es möglich eine Fußzeile zu erstellen?

Es gibt die Möglichkeit eine Zeile "einzufrieren".
Diese bleibt dann während eines Zeilen-Scroll-
Vorganges fixiert. Dies ist aber Excel-Like eher
für Kopfzeilen interessant.

dataGridView1.Rows[0].Frozen=true;

Man kann aber auch durch die Visible-Eigenschaft
dataGridView1.Rows[2].Visible = false;
Zellen nicht erscheinen lassen. Zusammen mit der
DataGridView.FirstDisplayedRow kann man beim
Scroll-Ereignis nur spezielle Rows sichtbar halten.

Für eine Fusszeile gibt es u.a. den Ansatz
eines durchsichtigen Bottom-gedockten Panels:

public Form1()
{ InitializeComponent(); //dgv -> dataGridView1
dgv.Rows.CollectionChanged += new
CollectionChangeEventHandler(Rows_CollectionChanged);
}
Panel pn = new Panel();
void Rows_CollectionChanged(object sender,CollectionChangeEventArgs e)
{ if (dgv.Rows.Count > 0)
{ if (!dgv.Controls.Contains(pn))
{ pn.Dock = DockStyle.Bottom;
pn.Height = dgv.Rows[0].HeaderCell.PreferredSize.Height;
pn.BackColor = Color.Transparent; dgv.Controls.Add(pn);
}
}
} // unterste Row wird dadurch nicht neugezeichnet


> 2.


> const string IDColumn = "ID";
> void LoadData()
> { DataGridViewRow row = (DataGridViewRow)dgView.RowTemplate.Clone();
> row.CreateCells(dgView);

> DataGridViewCell cell = row.Cells[IDColumn]; // Es gibt keinen.. Namen.
> } // Wozu sind dann die Namen da??

Deine "row" hängt noch im luftleeren Raum.
Sie ist nicht an ein DataColumn-Schema gebunden.


ciao Frank
--
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Marco von Frieling

unread,
Jan 8, 2006, 7:24:14 AM1/8/06
to
Hallo Frank,

> Es gibt die Möglichkeit eine Zeile "einzufrieren".
> Diese bleibt dann während eines Zeilen-Scroll-
> Vorganges fixiert. Dies ist aber Excel-Like eher
> für Kopfzeilen interessant.
Das ist mir bekannt.

>
> dataGridView1.Rows[0].Frozen=true;
>
> Man kann aber auch durch die Visible-Eigenschaft
> dataGridView1.Rows[2].Visible = false;
> Zellen nicht erscheinen lassen. Zusammen mit der
> DataGridView.FirstDisplayedRow kann man beim
> Scroll-Ereignis nur spezielle Rows sichtbar halten.
Dann müsste man ja aber irgendwie noch implementieren, dass die eine
Zeile immer unten sichtbar ist. Klingt erstmal recht kompliziert.

>
> Für eine Fusszeile gibt es u.a. den Ansatz
> eines durchsichtigen Bottom-gedockten Panels:
>
> public Form1()
> { InitializeComponent(); //dgv -> dataGridView1
> dgv.Rows.CollectionChanged += new
> CollectionChangeEventHandler(Rows_CollectionChanged);
> }
> Panel pn = new Panel();
> void Rows_CollectionChanged(object sender,CollectionChangeEventArgs e)
> { if (dgv.Rows.Count > 0)
> { if (!dgv.Controls.Contains(pn))
> { pn.Dock = DockStyle.Bottom;
> pn.Height = dgv.Rows[0].HeaderCell.PreferredSize.Height;
> pn.BackColor = Color.Transparent; dgv.Controls.Add(pn);
> }
> }
> } // unterste Row wird dadurch nicht neugezeichnet
Klingt sehr interessant, werde ich ausprobieren. Wenn sich nun der
Inhalt in der Fußzeile irgendwie ändert, reicht dann ein pn.Invalidate()
oder muss ich da noch etwas beachten, um die Fußzeile neu zeichnen zu
lassen?

Marco

Marco von Frieling

unread,
Jan 8, 2006, 7:36:11 AM1/8/06
to
Hallo nochmal,

>> 2.
>> const string IDColumn = "ID";
>> void LoadData()
>> { DataGridViewRow row = (DataGridViewRow)dgView.RowTemplate.Clone();
>> row.CreateCells(dgView);
>> DataGridViewCell cell = row.Cells[IDColumn]; // Es gibt keinen.. Namen.
>> } // Wozu sind dann die Namen da??
>
>
> Deine "row" hängt noch im luftleeren Raum.
> Sie ist nicht an ein DataColumn-Schema gebunden.
Das hatte ich irgendwie schon befürchtet. Ich habe jetzt hinter

row.CreateCells(dgView);

die row gleich dem dgView hinzugefügt statt erst wenn ich alle Zellen
gefüllt habe. Dann ist die row auch an das DataColumn-Schema gebunden,
aber irgendwie mache ich da immer noch etwas falsch. Denn

cell.Value = 133; // cell.ValueType == typeof(int)

wirft eine ArgumentOutOfRangeException, cell.Tag = 133; hingegen
funktioniert.

Message: "Specified argument was out of the range of valid values.
Parameter name: rowIndex"

rowIndex ist -1, aber warum, die Zeile habe ich doch schon zum
DataGridView hinzugefügt? Laut dgView.Rows hat die row aber den Index 0.

Gruß,
Marco

Frank Dzaebel

unread,
Jan 8, 2006, 1:16:10 PM1/8/06
to
Hallo Marco,

>> Für eine Fusszeile gibt es u.a. den Ansatz
>> eines durchsichtigen Bottom-gedockten Panels:

> Klingt sehr interessant, werde ich ausprobieren. Wenn sich nun der Inhalt in

> der Fußzeile irgendwie ändert, reicht dann ein pn.Invalidate() oder muss ich
> da noch etwas beachten, um die Fußzeile neu zeichnen zu lassen?

Im Prinzip reicht das, aber es gibt noch ein paar
"Kleinigkeiten" deswegen evtl. sauberer Ansatz :

public Form1()
{ InitializeComponent();
dgv.CellPainting += new DataGridViewCellPaintingEventHandler(
dgv_CellPainting);
dgv.Scroll += new ScrollEventHandler(dgv_Scroll);
dgv.Resize += new EventHandler(dgv_Resize);
}
void dgv_Scroll(object sender,ScrollEventArgs e)
{dgv.Invalidate();}
void dgv_Resize(object sender,EventArgs e)
{dgv.Invalidate();}
Font myFont = new Font("Arial",12,FontStyle.Bold);
Brush myBrush = Brushes.Blue;
Point myPoint = new Point(0,0);
Brush lyBrush = Brushes.LightYellow;
const int myColumn= 0;

void dgv_CellPainting(object sender,DataGridViewCellPaintingEventArgs e)
{ if (e.RowIndex == LastDisplayedRow())
if (e.ColumnIndex == myColumn)
{ e.Graphics.FillRectangle(lyBrush,e.CellBounds);
e.Graphics.DrawString("123,45",myFont,myBrush,e.CellBounds);
e.Handled = true; // für 123,45 dann die Summe einsetzen.
}
}

private int LastDisplayedRow()
{ for (int i=dgv.FirstDisplayedScrollingRowIndex;
i<dgv.Rows.Count; i++)
{ if (dgv.Rows[i].Displayed) continue; else return i-1;
} return -1;

Marco von Frieling

unread,
Jan 8, 2006, 2:14:57 PM1/8/06
to
Hallo Frank,

>> Wenn sich nun der
>> Inhalt in der Fußzeile irgendwie ändert, reicht dann ein
>> pn.Invalidate() oder muss ich da noch etwas beachten, um die Fußzeile
>> neu zeichnen zu lassen?
>
>
> Im Prinzip reicht das, aber es gibt noch ein paar
> "Kleinigkeiten" deswegen evtl. sauberer Ansatz :
Das sieht auf den ersten Blick verwirrend aus und ich habe heute abend
glaub ich keine Lust mehr mich damit noch zu befassen. Was die
"Kleinigkeiten" betrifft würde mich das schon genauer interessieren.
Vielleicht sehen wir uns ja Mittwoch im ifw Bremen und können im
Anschluss an den Vortrag ein wenig darüber diskutieren?

Gruß Marco

Frank Dzaebel

unread,
Jan 12, 2006, 11:22:17 AM1/12/06
to
Hallo Marco,

> DataGridView-Fusszeile möglich?

Für das DataGrid (.NET 1.1) habe ich hier noch
eine sehr umfangreiche Lösung von MS gefunden:

[How to sum the fields in a Windows Forms DataGrid control and display the
calculated totals in a footer by using Visual C# .NET]
http://support.microsoft.com/kb/842290/en-us

Frank Dzaebel

unread,
Jan 27, 2006, 2:56:26 PM1/27/06
to
... habe LastDisplayedRow() etwas verändert:

public Form1()
{ InitializeComponent();
dgv.CellPainting += new DataGridViewCellPaintingEventHandler(
dgv_CellPainting);
dgv.Scroll += new ScrollEventHandler(dgv_Scroll);
dgv.Resize += new EventHandler(dgv_Resize);
}
void dgv_Scroll(object sender,ScrollEventArgs e)
{dgv.Invalidate();}
void dgv_Resize(object sender,EventArgs e)
{dgv.Invalidate();}
Font myFont = new Font("Arial",12,FontStyle.Bold);
Brush myBrush = Brushes.Blue;
Point myPoint = new Point(0,0);
Brush lyBrush = Brushes.LightYellow;
const int myColumn= 0;

void dgv_CellPainting(object sender,DataGridViewCellPaintingEventArgs e)
{ if (e.RowIndex == LastDisplayedRow())
if (e.ColumnIndex == myColumn)
{ e.Graphics.FillRectangle(lyBrush,e.CellBounds);
e.Graphics.DrawString("123,45",myFont,myBrush,e.CellBounds);
e.Handled = true; // für 123,45 dann die Summe einsetzen.
}
}

private int LastDisplayedRow()
{
if (dgv.FirstDisplayedScrollingRowIndex < 0) return -1;
for (int i = dgv.FirstDisplayedScrollingRowIndex;


i < dgv.Rows.Count; i++)
if (dgv.Rows[i].Displayed) continue; else return i - 1;

return dgv.Rows.Count - 1;

Marco von Frieling

unread,
Jan 28, 2006, 7:00:39 AM1/28/06
to
Hallo Frank,

> ... habe LastDisplayedRow() etwas verändert:
mit zwei Zeilen sieht es jetzt besser aus. Die Fußzeile wird immer als
letzte Zeile angezeigt, zwar immer noch nicht am unteren Rand wie es mal
werden soll, aber das ist im Moment nicht ganz so wichtig.

Ich muss jetzt erst mal die eigentliche Logik voranbringen.

Gruß Marco

Marco von Frieling

unread,
Jan 29, 2006, 1:26:23 PM1/29/06
to
> mit zwei Zeilen sieht es jetzt besser aus. Die Fußzeile wird immer als
> letzte Zeile angezeigt, zwar immer noch nicht am unteren Rand wie es mal
> werden soll, aber das ist im Moment nicht ganz so wichtig.
Nachtrag: Mit 40 Zeilen springt die Fußzeile beim Scrollen hin und her
(d. h. in Scrollrichtung), steht danach aber wieder an der richtigen
Stelle. Gibt es da eine Möglichkeit, das zu verhindern, etwa
OnScrollBegin und OnScrollEnd oder etwas Derartiges?

Gruß
Marco

Frank Dzaebel

unread,
Jan 29, 2006, 2:50:26 PM1/29/06
to
Hallo Marco,

> Nachtrag: Mit 40 Zeilen springt die Fußzeile beim Scrollen hin und her (d. h.
> in Scrollrichtung), steht danach aber wieder an der richtigen Stelle. Gibt es
> da eine Möglichkeit, das zu verhindern, etwa OnScrollBegin und OnScrollEnd
> oder etwas Derartiges?

Meinst Du, dass die Zeile einen kurzen Augenblick
beim Scrollen eine Zeile höher gezeichnet wird und dann
wieder als Fusszeile korrekt?

Frank Dzaebel

unread,
Jan 29, 2006, 5:04:57 PM1/29/06
to
Hallo Marco,

> Meinst Du, dass die Zeile einen kurzen Augenblick
> beim Scrollen eine Zeile höher gezeichnet wird und dann
> wieder als Fusszeile korrekt?

Wenn ja, mach z.B. folgendes:

a) Lösche den Code für das dgv_Scroll(obj,...) Event ersatzlos.

b) Subclass'e das DataGridView:

class MyDataGridView : DataGridView
{ public MyDataGridView()
{ this.VerticalScrollBar.ValueChanged +=
new EventHandler(VSB_ValueChanged);
}
void VSB_ValueChanged(object sender,EventArgs e)
{ this.Invalidate(); }
}

c) ersetze die beiden Vorkommen der DataGridView-
Definition durch MyDataGridView.

Wird ja langsam ganz brauchbar :)

Sieber Christoph

unread,
Feb 26, 2006, 7:21:50 AM2/26/06
to
HI

ich habe auch ein änliches Problem. Ich habe ein dataTable und dies
wird in einem GridView angezeigt.

jetzt habe ich ja die einfache Möglichkeit über VS2005 dem GridView
einen Header und Footer anzufügen. Wie greife ich jetzt aber im Code
auf die einzelnen Zellen im Footer zu? das heist konkret, ich möchte
im footer jeder Spalte einen beliebigen Wert schreiben.

ich habe das hier im Beitrag nicht gefunden oder habe es übersehen.

Grüsse

Christoph

Frank Dzaebel

unread,
Feb 26, 2006, 10:42:36 AM2/26/06
to
Hallo Christoph,

Das ist in ASP.NET 2.0. Wir sprachen ja bislang
über ein WinForm-DataGridView, aber ok.
Da würde mans (als Beispiel) etwa so machen:

GridViewRow footerRow;
protected void Page_Load(object sender,EventArgs e)
{ GridView1.ShowFooter = true;
footerRow = GridView1.FooterRow;
DataControlFieldCell dfc0 = (DataControlFieldCell)footerRow.Cells[0];
dfc0.Text = "Hallo";
DataControlFieldCell dfc1 = (DataControlFieldCell)footerRow.Cells[1];
dfc1.Text = "Christoph!";

Sieber Christoph

unread,
Feb 27, 2006, 5:08:02 AM2/27/06
to
Hallo Frank

>GridViewRow footerRow;
>protected void Page_Load(object sender,EventArgs e)
>{ GridView1.ShowFooter = true;
> footerRow = GridView1.FooterRow;
> DataControlFieldCell dfc0 = (DataControlFieldCell)footerRow.Cells[0];
> dfc0.Text = "Hallo";
> DataControlFieldCell dfc1 = (DataControlFieldCell)footerRow.Cells[1];
> dfc1.Text = "Christoph!";
>}

Dieser code geht bei mir leider nicht, da ich ein DataGrid und kein
GridView verwende. Ich könnte jetzt zwar ein GridView verwenden, aber
dann funktioniert der Export ins Excel wieder nicht.

hast du mir evt. ein Tipp, wie ich das mit einem DataGrid lösen
könnte?

grüsse

christoph

Frank Dzaebel

unread,
Feb 27, 2006, 7:01:53 AM2/27/06
to
Hallo Christoph,

>Dieser code geht bei mir leider nicht, da ich ein DataGrid und kein
>GridView verwende. Ich könnte jetzt zwar ein GridView verwenden, aber
>dann funktioniert der Export ins Excel wieder nicht.

Also der sollte eigentlich funktionieren, wenn auch
mit ggf. abgeändertem Code.

>hast du mir evt. ein Tipp, wie ich das mit einem DataGrid lösen
>könnte?

Für das .NET 1.1 DataGrid ist eine FooterRow wegen
(zumindest) fehlendem CellPainting Event recht schwierig
zu machen. Ich würde da evtl. einfach unter das DataGrid-
Control TextBoxen mit der "Column.Width" der DataGrid-Spalten
einfügen. Dann sollte das Grid möglichst keinen horizontalen
Scrollbar haben, da die Summen da (normal) dann nicht
mitwandern. Ausserdem feste nicht änderbaren Breiten der
DataGrid-Spalten.

Sieber Christoph

unread,
Feb 27, 2006, 7:42:15 AM2/27/06
to
hej

>Also der sollte eigentlich funktionieren, wenn auch
>mit ggf. abgeändertem Code.

ich bekomme hier den Fehler:

footerRow = dg.FooterRow;

da das DataGrid keine Definition für 'FooterRow' hat. das GridView hat
es allerdings.

kann ich das irgendwie umproggen? ich konnte die Daten schon in eine
neue Row machen und diese dann im DataGrid anzeigen lassen, aber da
kann ich den Text nicht Fett machen und auch keine andere
Hintergrundfarbe hinzufügen. Im Footer wäre dies dann aber schon der
Fall. Also vielelicht geht es ja schon, habe aber nichts gefunden im
netz.

grüsse

christoph

Frank Dzaebel

unread,
Feb 27, 2006, 8:57:30 AM2/27/06
to
Hallo Christoph,

>Also der sollte eigentlich funktionieren, wenn auch
>mit ggf. abgeändertem Code.
>ich bekomme hier den Fehler:
>footerRow = dg.FooterRow;

eben, ich sagte ja auch, dass eine FooterRow
für das DataGrid 1.1 schwer zu machen sei, und
dass ich eben an Deiner Stelle eigene TextBoxen
unter das Grid zeichnen würde.
Oder gibt es da einen bestimmten Grund, warum das
bei Dir nicht gehen sollte?

Sieber Christoph

unread,
Feb 27, 2006, 9:32:21 AM2/27/06
to
Hi Frank

>Oder gibt es da einen bestimmten Grund, warum das
>bei Dir nicht gehen sollte?

wenn ich eine Textbox darunter mache, dann wird mir diese danach nicht
ins Excel exportiert. Ich verwende .NET 2.0 ist es da auch schwer zu
machen?

gruss

christoph

Frank Dzaebel

unread,
Feb 27, 2006, 10:01:41 AM2/27/06
to
Hallo Christoph,

Au, dann haben wir etwas aneinander vorbeigeredet.
Ich frage jetzt lieber nochmal.

Du verwendest also unter .NET 2.0 das DataGrid?
Als WinForm oder Web-Control?
... DataGrid ([1.1 WinForm], [1.1 ASP.NET]), aber unter 2.0 möglich
... DataGridView (WinForm nur 2.0)
.. GridView (ASP.NET 2.0)
hier ständig durcheinanderwirbeln ...
Jedenfalls schon mal vielversprechend, wenn
Du .NET 2.0 benutzt.


[zum Excel-Export:]
Das ist ja eigentlich nur so, das der DataSource
mit einem bestimmten Code nach Excel transferiert wird.
Gibt es aber wieder 100 Möglichkeiten.
Wie sieht denn der Code zum Transferieren nach Excel
aus?

Sieber Christoph

unread,
Feb 27, 2006, 1:07:49 PM2/27/06
to
Hi Frank

>Du verwendest also unter .NET 2.0 das DataGrid?
>Als WinForm oder Web-Control?
>... DataGrid ([1.1 WinForm], [1.1 ASP.NET]), aber unter 2.0 möglich
>... DataGridView (WinForm nur 2.0)
>.. GridView (ASP.NET 2.0)

also ich habe eine WebAnwendung und habe da ein DataGrid unter .NET
2.0!

Wie gesagt, das DataGrid kann ich exportieren, verwende ich aber ein
DataGridView, bekomme ich beim Export ein Fehler von wegen dass das
Control nicht in den HTML tags liegt.

Desshalb würde ich gerne meine Daten in den Footer vom DataGrid
schreiben und müsste somit nichts mehr anpassen.

Grüsse

Christoph

Frank Dzaebel

unread,
Feb 27, 2006, 2:53:59 PM2/27/06
to
Hallo Christoph,

>also ich habe eine WebAnwendung und habe da ein
> DataGrid unter .NET 2.0!

Leider ist da die Antwort zu meiner Frage nach einem
(Ansatz) Code des Exportes nach Excel noch nicht dabei.
Aber ok, auf die FooterRow im DataGrid unter 2.0
kannst Du z.B. folgendermassen zugreifen:

protected void Page_Load(object sender, System.EventArgs e)
{ if (!IsPostBack)
{ oleDbDataAdapter1.Fill(dataSet11); // als Beispiel
this.DataBind();
}
if (footerRow != null)
{ footerRow.Cells[0].Text = "123"; // oder auslesen
footerRow.Cells[1].Text = "123";
}
}

DataGridItem footerRow;
protected void DataGrid1_ItemDataBound(object sender,DataGridItemEventArgs e)
{ if (e.Item.ItemType == ListItemType.Footer) footerRow = e.Item;
}


siehe auch:

[Pager- und Footerzeilen des DataGrid erweitern]
http://www.aspheute.com/artikel/20040318.htm

Sieber Christoph

unread,
Feb 28, 2006, 3:38:32 AM2/28/06
to
Hi Frank

hier noch der Export ins Excel. Ich hatte gestern den code nicht zur
Hand.

//SC: START EXPORT data ins Excel
protected void Button1_Click(object sender, EventArgs e)
{
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/vnd.ms-excel";
Response.Charset = "";
this.EnableViewState = false;
System.IO.StringWriter oStringWriter = new
System.IO.StringWriter();
System.Web.UI.HtmlTextWriter oHtmlTextWriter = new
System.Web.UI.HtmlTextWriter(oStringWriter);
this.ClearControls(dg);
dg.RenderControl(oHtmlTextWriter);
Response.Write(oStringWriter.ToString());
Response.End();
}


private void ClearControls(Control control)
{
for (int i = control.Controls.Count - 1; i >= 0; i--)
{
ClearControls(control.Controls[i]);
}

if (!(control is TableCell))
{
if (control.GetType().GetProperty("SelectedItem") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
try
{
literal.Text =
(string)control.GetType().GetProperty("SelectedItem").GetValue(control,
null);
}
catch
{

}

control.Parent.Controls.Remove(control);
}

else

if (control.GetType().GetProperty("Text") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
literal.Text =
(string)control.GetType().GetProperty("Text").GetValue(control, null);
control.Parent.Controls.Remove(control);
}
}
return;
}

//SC: END EXPORT data ins Excel

das mit dem Footer hat geklappt... DANKE

gruss

Christoph

0 new messages