A mellékelt alkalmazás mappájának AutoSizeDGColumnLibrary nevű alkönyvtárában találjuk meg a kontrol forráskódját, melyet lefordítva kapjuk meg a kontrol kódját tartalmazó .DLL állományt. Felhasználás előtt fel kell vennünk a kontrolt ToolBox-ba.
Kontrolunk osztályához egy property-t adtunk, melynek segítségével megadható már szerkesztési időben, hogy az adathalmaz megjelenítésekor kívánjuk-e használni az oszlopok automatikus méretezését, vagy sem. A property, valamint az általa állított változó deklarációja a következő:
private bool columnsautosize = true;
public bool ColumnsAutoSize
{
get
{
return columnsautosize;
}
set
{
columnsautosize = value;
}
}
A kontrol konstruktorában deklarálunk egy kezelőt ahhoz az eseményhez, amikor az adatforrás megadásra kerül a kontrol DataSource property-jén keresztül:
public AutoSizeDGColumnControl()
{
this.DataSourceChanged += new System.EventHandler(this.control_DSChanged);
}
Kontrolunkat felkészítettük két lehetséges esetre abból a szempontból, hogy az adatforrást milyen osztály formájában adtuk meg, tudvalevő ugyanis, hogy a DataSource property object típusú, így mind DataTable, mind DataView osztályú objektum átadható adatforrásként.
if (this.DataSource.GetType().ToString() == "System.Data.DataTable")
{
dt = ((DataTable)this.DataSource);
}
else if (this.DataSource.GetType().ToString() == "System.Data.DataView")
{
dt = ((DataView)this.DataSource).Table;
}
A kontrol GetMaxColumnWidth metódusában meghatározzuk, hogy az adott adatforrás hány oszloppal rendelkezik, valamint a rekordokban tárolt adatok közül hány karakter hosszú a leghosszabb adat. Ezek ismeretében a Graphics osztály segítségével megadjuk az egyes oszlopok majdani szélességét pixelben, ezeket eltároljuk egy ArrayList listában. Ezen adatok már konkrétan felhasználhatók a méretezéshez. Mindezen számítások csak akkor futnak le, ha a ColumnsAutoSize property TRUE értékű. A megoldásban két FOR ciklussal megyünk végig a tábla rekordjain, majd meghatározzuk a leghosszabb elem hosszát:
Graphics g = Graphics.FromHwnd(this.Handle);
SizeF s;
...
Az oszlopok vizsgálata, amikor megvizsgáljuk az oszlopok fejlécét is:
for(int i=0;i<dt.Columns.Count;i++)
{
maxlength = dt.Columns[i].Caption.Length;
maxstr = dt.Columns[i].Caption;
A belső ciklusban a rekordok vizsgálata a leghosszabb elem keresésével:
for(int j=0;j<dt.Rows.Count;j++)
{
if (dt.Rows[j][i].ToString().Length > maxlength)
{
maxlength = dt.Rows[j][i].ToString().Length;
maxstr = dt.Rows[j][i].ToString();
}
}
A Graphics osztály metódusával egy SizeF struktúrába tesszük az adott karakterlánc méretadatait pixelben, a használt betűtípus ismeretében:
s = g.MeasureString(maxstr, this.Font);
Ennek szélesség értékét egészre konvertáljuk, és betesszük a listába, melyet a metódus visszaad:
curLength = Convert.ToInt32(s.Width+15);
columnWidths.Add(curLength);
...
}
A kontrol DoAutoSize metódusában méretezzük az oszlopokat. Megadunk egy CurrencyManager objektumot, mely kapcsolatot teremt a kontrol és az adatforrás közt:
private void DoAutoSize(ArrayList l)
{
CurrencyManager cm = (CurrencyManager)this.BindingContext[this.DataSource];
Megadunk egy, a kontrol stílusát reprezentáló objektumot:
DataGridTableStyle ts = new DataGridTableStyle(cm);
Az objektum oszlopstílusokkal rendelkezik, melyeknek már állítható a szélesség értéke. Ezeket az adatokat kapja a metódus paraméterként a listában:
for(int i=0;i<l.Count;i++)
{
ts.GridColumnStyles[i].Width = Convert.ToInt32(l[i]);
}
A kontrol TableStyles nevű stílusgyűjteményéhez hozzáfűzzük a stílusobjektumot:
this.TableStyles.Add(ts);
}
Az utóbbi két metódust a deklarált eseménykezelőben hívjuk meg:
private void control_DSChanged(object sender, EventArgs e)
{
ArrayList wList = new ArrayList();
wList = GetMaxColumnWidth();
DoAutoSize(wList);
}
Az alkalmazásban csupán annyi a dolgunk, hogy egy adatszerkezetet feltöltsünk adatokkal, és ezt a kontrolunk DataSource property-jén keresztül adatforrásként átadjuk neki. Az alkalmazás mappájában elhelyeztünk egy XML állományt, mely tartalmazza az adatokat. Ezt a DataSet objektum ReadXml metódusával olvassuk be.