Mehr von Jürgen Gutsch

Mehr von Jürgen Gutsch

Empfehlungen von Jürgen Gutsch

Blog-Empfehlungen von Jürgen Gutsch

Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

Jürgen Gutsch

ASP.NET und mehr...

News

Eigene Spaltentypen für das GridView erstellen

Mit den gegebenen Spaltentypen für GridViews stößt man immer wieder schnell an die Grenzen desselben. Man könnte zwar mit einem TemplateField eigene, selbstdefinierte Spalten erzeugen, was allerdings nur was bringt, wenn man die Spalte per ASP.NET Markup einfügen kann. Oft kommt es aber vor, dass man ein GridView Codeseitig einbinden (z. B: wenn man ein eigenes Control, das ein GridView beinhaltet, in einer separaten Control Library auslagern möchte), oder Codeseitig bestimmte Spalten hinzufügen möchte.

Die einfachste Lösung ist dann nur ein eigenes Feld, das von DataControlField erbt. Im Prinzip ist es ganz einfach eigene Felder (z. B: ein spezialisiertes Feld für Numerische Werte) zu schreiben.

Wie bereits geschrieben, muss das neue Feld vom DataControlField erben:
public class NumericField : DataControlField
{
}

Folgende Eigenschaften definiere ich für mein "NumericField":
// enthält den Namen der Tabellenspalte
public string DataField
{
  get
  {
    object value = base.ViewState["DataField"];
    if (value != null)
      return value.ToString();
    else
      return string.Empty;
  }
  set
  {
    base.ViewState["DataField"] = value;
    this.OnFieldChanged();
  }
}
// ein Formatstring für numerische Werte
public string FormatString
{
  get
  {
    object value = base.ViewState["FormatString"];
    if (value != null)
      return value.ToString();
    else
      return string.Empty;
  }
  set
  {
    base.ViewState["FormatString"] = value;
    this.OnFieldChanged();
  }
}
// eine Feste Breite für das Feld
public Unit Width
{
  get
  {
    object value = base.ViewState["Width"];
    if (value != null)
      return (Unit)value;
    else
      return Unit.Empty;
  }
  set
  {
    base.ViewState["Width"] = value;
    this.OnFieldChanged();
  }
}
// und die Textausrichtung,
public HorizontalAlign Alignment
{
  get
  {
    object value = base.ViewState["Alignment"];
    if (value != null)
      return (HorizontalAlign)value;
    else
      return HorizontalAlign.Left;
  }
  set
  {
    base.ViewState["Alignment"] = value;
    this.OnFieldChanged();
  }
}

Folgende Methode muss (da als abstrakte Methode definiert) überschreiben werden:
protected override DataControlField CreateField()
{
  return new NumericField ();
}

Sie muss nur eine Instanz der aktuellen Klasse zurückgeben

Die nächste Methode die Überschrieben wird, steuert die Ausgabe der Tabellenzelle. (In diesem Beispiel wird nur die Datenzelle von mir verändert) auf die gleiche Art kann auch eine selbstdefinierte Footer-, oder Header Zelle erzeugt werden (Um z. B: im Footer die Summe der Spaltenwerte zusammenzufassen, oder im Header weitere Funktionen zur Verfügung zu stellen)

public override void InitializeCell(DataControlFieldCell cell,
    DataControlCellType cellType,
    DataControlRowState rowState, int rowIndex)
{
  base.InitializeCell(cell, cellType, rowState, rowIndex);
  switch (cellType)
  {
    //case DataControlCellType.Header:
    //  this.InitializeHeaderCell(cell, rowState);
    //  break;
    case DataControlCellType.DataCell:
      this.InitializeDataCell(cell, rowState);
      break;
    //case DataControlCellType.Footer:
    //  this.InitializeFooterCell(cell, rowState);
    //  break;

  }
}

Die Methode InitializeDataCell sieht wie folgt aus:
protected void InitializeDataCell(DataControlFieldCell cell,
    DataControlRowState rowState)
{
  cell.Controls.Clear();
  Panel lblText = new Panel();
  // folgende Styleangaben schneiden überlange Inhalte ab.
  lblText.Style.Add("white-space", "nowrap");
  lblText.Style.Add("display", "block");
  lblText.Width = this.Width;
  lblText.Style.Add("height", "auto");
  lblText.Style.Add("overflow", "hidden");
  // Ausrichtung
  if (this.Alignment == HorizontalAlign.Right)
    lblText.Style.Add("text-align", "right");
  lblText.DataBinding += new EventHandler(lblText_DataBinding);
  cell.Controls.Add(lblText);
}

Der Eventhandler für das DataBinding
void lblText_DataBinding(object sender, EventArgs e)
{
  Panel target = sender as Panel;
  GridViewRow container = target.NamingContainer as GridViewRow;
  // Referenz des DataRowView Objektes erhalten
  Object dataItem = null;
  dataItem = DataBinder.GetDataItem(container) as DataRowView;
  if (dataItem == null) // tritt ein, wenn an ein Objekt gebunden wird
    dataItem = DataBinder.GetDataItem(container);
  Object dataFieldValue = null;
  if (this.DataField.Contains(".")) // für den Fall das ChildValues angezeigt werden sollen
    dataFieldValue = DataBinder.Eval(dataItem, this.DataField);
  else // Normalfall (ist schneller)
    dataFieldValue = DataBinder.GetPropertyValue(dataItem, this.DataField);
  // Wert prüfen und bearbeiten und formatieren
  if (dataFieldValue != null)
  {
    float value = 0F;
    if (float.TryParse(dataFieldValue.ToString(), out value))
      if (!string.IsNullOrEmpty(this.FormatString))
        dataFieldValue = value.ToString(this.FormatString);
      else
        dataFieldValue = value.ToString();
    // Wert ausgeben
    target.ToolTip = dataFieldValue.ToString();
    target.Controls.Add(new LiteralControl(
        HttpUtility.HtmlEncode(dataFieldValue.ToString())));
  }
}

Um das gleiche wie in Peters Blogeintrag "Zeilennummer im GridView anzeigen" (1) zu erzeugen, könnte der DataBinding EventHandler in etwa folgendermaßen aussehen:
void lblText_DataBinding(object sender, EventArgs e)
{
  Panel target = sender as Panel;
  GridViewRow container = target.NamingContainer as GridViewRow;
  // Wert ausgeben
  target.ToolTip = dataFieldValue.ToString();
  target.Controls.Add(new LiteralControl(
      HttpUtility.HtmlEncode(container.DataItemIndex + 1)));
  }
}

(1) http://www.aspnetzone.de/blogs/peterbucher/archive/2007/10/10/zeilennummer-im-gridview-anzeigen.aspx

Share this post:
Posted: Mittwoch, 17. Oktober 2007 16:24 von Jürgen Gutsch
Abgelegt unter: , , ,
Anonyme Kommentare sind nicht zugelassen