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;
      }
    }
  }
}