Multiline DataGrid
Frank Dzaebel, erstellt am: 16.6.2005, zuletzt geändert: 16.6.2005
DataGrid: Implementation, .NET-Version: 1.1, [Download]
Das DataGrid stellt normalerweise nur bei Klick eine Zelle umgebrochen dar.
Wie das zu ändern ist und gleichzeitig dynamisch berechnete Zeilen-Höhen erreichbar sind, zeigt die nachstehende Lösung. Zusammen mit dem Projekt DataGridBrowser [SyncFusion] kann man sich ein kleines Test-Projekt zusammen bauen.
Das Ergebnis sieht dann etwa so aus :
Der Lösungsansatz ist, dass die TextBox komplett selber gezeichnet wird.
Je nach gemessener String-Länge wird die Höhe dynamisch angepasst.
Im DataGridBrowser-Projekt in Form1.cs noch folgendes ändern :
using Wcsg.UI.Windows;
DataGridMultiLineTextBox aColumnTextColumn ;
for(int i = 0; i < numCols; ++i)
{
aColumnTextColumn = new DataGridMultiLineTextBox(); // Rest weggelassen.
/* Konzept und viel von dem Code ist von: Ken Tucker (Microsoft MVP / VIP)*/
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.Collections;
namespace Wcsg.UI.Windows
{
/// <summary>Datagrid column that
displays text in a multiline, word-wrapped textbox</summary>
public class DataGridMultiLineTextBox : DataGridTextBoxColumn
{
private HorizontalAlignment dataAlignment;
private StringFormat mDrawText = new StringFormat();
private bool mbAdjustHeight = true; // added by FD
private ArrayList arrHeights;
private DataGrid dg;
public HorizontalAlignment DataAlignment
{
get
{
return dataAlignment;
}
set
{
dataAlignment = value;
switch (dataAlignment)
{
case HorizontalAlignment.Center:
mDrawText.Alignment = StringAlignment.Center;
break;
case HorizontalAlignment.Right:
mDrawText.Alignment = StringAlignment.Far;
break;
case HorizontalAlignment.Left:
mDrawText.Alignment = StringAlignment.Near;
break;
}
}
}
public DataGridMultiLineTextBox()
{
dataAlignment = HorizontalAlignment.Left;
mDrawText.Alignment = StringAlignment.Near;
// this.ReadOnly = true; // commented out by Dzaebel
}
private void getHeightList()
{
MethodInfo mi = dg.GetType().GetMethod("get_DataGridRows", BindingFlags.FlattenHierarchy |
BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Static);
System.Array dgra = (System.Array)(mi.Invoke(this.dg, null));
arrHeights = new ArrayList();
foreach (Object dgRowHeight in dgra)
{
if (dgRowHeight.ToString().EndsWith("DataGridRelationshipRow"))
{
arrHeights.Add(dgRowHeight);
}
}
}
protected override void Edit(CurrencyManager source, int rowNum, Rectangle bounds,
bool readOnly, String instantText, bool cellIsVisible)
{
base.Edit (source, rowNum, bounds, readOnly, instantText, cellIsVisible);
this.TextBox.TextAlign = this.dataAlignment;
this.TextBox.Multiline = this.mbAdjustHeight;
if (rowNum == source.Count - 1)
{
this.getHeightList();
}
}
protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source,
int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
{
bool bPainted = false;
if (!bPainted)
{
this.dg = this.DataGridTableStyle.DataGrid;
this.getHeightList();
}
// clear the cell
g.FillRectangle(backBrush, bounds);
// draw the value
String s = this.GetColumnValueAtRow(source, rowNum).ToString();
Rectangle r = new Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height);
r.Inflate(0, -1);
// determine the appropriate column height
SizeF sDraw = g.MeasureString(s, this.TextBox.Font, this.Width, mDrawText);
int h = (int)(sDraw.Height + 5);
if (mbAdjustHeight)
{
try
{
PropertyInfo propInfo = arrHeights[rowNum].GetType().GetProperty("Height");
// get the current height
int currentHeight = (int)propInfo.GetValue(arrHeights[rowNum], null);
// adjust the height
if (h>currentHeight)
{
propInfo.SetValue(arrHeights[rowNum], h, null);
Size size = dg.Size;
dg.Size = new Size(size.Width, size.Height - 10);
dg.Size = size;
}
}
catch (Exception ex)
{
// something went wrong, restore the default height
this.getHeightList();
}
g.DrawString(s, base.TextBox.Font, foreBrush, r, mDrawText);
bPainted = true;
}
}
}
}