Peter Bucher - Mein Experiment, meine Spielereien, meine Welt...   ·   Stefan Falz   ·   Jürgen Gutsch   ·   Golo Roden   ·   ASP.NET Zone   ·   Microsoft ASP.NET
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

Ausgabe eines GridViews verändern - DataBound und RowDataBound Events

Vielfach kam in den Communities die Frage auf, wie es sich denn die Anzeige des GridViews verändern lässt.
Als Antwort kommt "RowDataBound Event".

Genau auf diesen Event will ich hier eingehen und anhand eines Beispiels zeigen, wie dieser Event benutzt werden kann.

Zitat aus "Hinweise":

Bevor das GridView-Steuerelement gerendert werden kann, muss jede Zeile im Steuerelement an einen Datensatz in der Datenquelle gebunden werden. Das RowDataBound-Ereignis wird ausgelöst, wenn eine Datenzeile (dargestellt durch ein GridViewRow-Objekt) an Daten im GridView-Steuerelement gebunden wird. Dadurch können Sie eine Ereignisbehandlungsmethode bereitstellen, die bei jedem Auftreten dieses Ereignisses eine benutzerdefinierte Routine ausführt, beispielsweise das Ändern der Werte der an die Zeilen gebundenen Daten.

 

und es steht weiter...

Ein GridViewRowEventArgs-Objekt wird an die Ereignisbehandlungsmethode übergeben, wodurch Sie auf die Eigenschaften der gebundenen Zeile zugreifen können. Wenn Sie auf eine bestimmte Zelle in der Zeile zugreifen möchten, verwenden Sie die Cells-Eigenschaft des GridViewRow-Objekts, das in der Row-Eigenschaft des GridViewRowEventArgs-Steuerelements enthalten ist. Sie können außerdem bestimmen, welcher Zeilentyp (Headerzeile, Datenzeile usw.) gebunden wird, indem Sie die RowType-Eigenschaft verwenden.

Das heisst, mit dem Event "RowDataBound" der GridView Klasse, ist es möglich, jede Zeile direkt nach der Datenbindung zu modifizieren.

Methoden die das Ereignis abonnieren, müssen einer festgelegten Signatur entsprechen.
Visual Studio macht das im Normalfall selber per Tastenkombination für uns.

 

Folgende, die benötigte Signatur:

void grdTest_RowDataBound(object sender, GridViewRowEventArgs e)

 

Eine Methode kann bspw. so aussehen:



/// <summary>
/// Formatiert die Tabelle ansehlich
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundAllgemein(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        string text = e.Row.Cells[2].Text;
        e.Row.Cells[2].Text = Tools.WordWrap(text, 25) + "...";
        e.Row.Cells[2].CssClass = "fixedWidth";
    }
}

GridViewDataBoundEvents

Diese macht nichts weiter, als für alle Zeilen die dem DataControlRowType.DataRow entsprechen, denn Text zu kürzen und der dritten Zelle von Links eine CSS Klasse hinzuzufügen, damit sie eine fixe Breite einnimmt.

 

Zum Download findet ihr eine Beispielanwendung, diese enthält ein GridView das mit Zufallsdaten gefüllt wird.
Mit vier Behandlungsmethoden für DataBound und RowDataBound enthält und die Tabelle in der Ausgabe modifiziert.
Mithilfe des Suchfilters können Textdaten aus dem Feld "Text" hervorgehoben werden, die dem Suchwort entsprechen.

Mit dem Priority-Farbe Link können die Farben für die Priority Spalte hervorgehoben werden
Mithilfe des Priority-Summe Links wird in der FooterRow (Fuss-Zeile) jeweils eine Summe aller Priorities dargestellt.
Im nächsten Abschnitt findet ihr den benötigten ASPX Code, den ich der Übersichtshalber ein bisschen beschnitten habe:

 

 

 



<form id="aspnetform" defaultbutton="btnSubmit" runat="server">
    <h1>GridViewDataBoundEvents</h1>
    <asp:Label ID="lblSearch" AssociatedControlID="txtSearch" Text="Suche in Text" runat="server" />
    <asp:TextBox ID="txtSearch" runat="server" />
    <asp:Button ID="btnSubmit" Text="Finden" runat="server" />
    <br />
    <br />
    <a id="search" href="?mode=search" runat="server">Suchfilter</a>
    <a id="color" href="?mode=color" runat="server">Priority-Farbe</a>
    <a id="sum" href="?mode=sum" runat="server">Priority-Summe</a>
    <br />
    <br />
    <asp:GridView ID="grdTest" GridLines="None" runat="server" />
</form>

Es steht ein Suchformular zur Verfügung, das aktiv wird, wenn der Suchfilter aktiviert wird.
Die kleine Navigation mit den normalen Links soll euch zeigen, wie verschiedene RowDataBound Ereignishandler je nach Auswahl abonniert werden können.

Im Page_Load der Beispielseite werden die Daten aus einer Zufallsquelle geladen, die Filter je nach Auswahl zugewiesen und dem aktiven Link eine CSS Klasse hinzugefügt.
Zudem werden die Daten beim ersten Laden der Seite gebunden und ein Klick Event des Suchen Buttons registriert.



protected void Page_Load(object sender, EventArgs e) {
    // Daten besorgen
    List<Task> data                  = new RandomData(10).RandomList;
    this.grdTest.DataSource      = data;

    // Filter Mode auswählen
    string mode = this.Request.QueryString["mode"];
    if (string.IsNullOrEmpty(mode)) {
        mode = String.Empty;
    }

    // Allgemeine Formatierungen anwenden
    this.grdTest.RowDataBound += this.grdTest_RowDataBoundAllgemein;

    switch (mode) {
        case "sum":
            // Summe anzeigen
            this.grdTest.DataBound += grdTest_DataBound;
            this.sum.Attributes.Add("class", "active");
            break;
        case"color":
            // Farben zu den Priority Zahlen anzeigen
            this.grdTest.RowDataBound += this.grdTest_RowDataBoundPriorityBackColor;
            this.color.Attributes.Add("class", "active");
            break;
        case "search":
            // Suchwörter bzw. dessen Zeilen hervorheben
            this.grdTest.RowDataBound += this.grdTest_RowDataBoundTextSearch;
            this.search.Attributes.Add("class", "active");
            break;
        default:
            break;
    }

    // Button.Click Eventhandler anmelden
    this.btnSubmit.Click += this.btnSubmit_Click;

    // Daten beim ersten Seitenaufruf binden
    if (!this.IsPostBack) {
        this.grdTest.DataBind();
    }
}

 

Diese Routine hebt Texte hervor, die ein Treffer in der Suche haben



/// <summary>
/// Erhellt die Zeilen, bei denen ein der gesuchte Begriff von "txtSearch" vorkommt
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundTextSearch(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        string text = e.Row.Cells[2].Text;
        if ((!string.IsNullOrEmpty(this.txtSearch.Text))
            && text.IndexOf(this.txtSearch.Text) > -1) {
            e.Row.Cells[2].ForeColor = Color.Red;
        }
    }
}

 

Diese Methode vergibt Farben, je nach dem was für Werte das Feld "Priority" enthält.
Hier wird direkt über die DataBinder.Eval() Methode gearbeitet. Das ist genauer als über die jeweilige Zelle zu gehen.

Denn die Zelle, bzw. dessen Index kann sich ändern, ein Feldname nicht so häufig.



/// <summary>
/// Vergibt je nach Zahlenwertung eine Hintergrundfarbe für die aktuelle Zelle
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest_RowDataBoundPriorityBackColor(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        TableCell priortyCell = e.Row.Cells[3];

        switch(int.Parse(DataBinder.Eval(e.Row.DataItem, "Priority").ToString())) {
            case 0:
            case 1:
            case 2:
                priortyCell.BackColor = Color.Gray;
                break;
            case 3:
            case 4:
            case 5:
                priortyCell.BackColor = Color.Orange;
                break;
            case 6:
            case 7:
            case 8:
                priortyCell.BackColor = Color.OrangeRed;
                break;
            case 9:
            case 10:
                priortyCell.BackColor = Color.Red;
                break;
            default:
                break;
        }
    }
}

 

Und was passiert jetzt, wenn ich TemplateFields habe?

Wenn die Vorgaben nicht passend sind, ist ein TemplateField Mittel zum Zweck und dazu noch ein gutes!
In einem ItemTemplate eines TemplateFields können beliebige Controls platziert werden, bspw.:

Folgend der Code, des zweiten GridViews:



<asp:GridView ID="grdTest2" AutoGenerateColumns="false" GridLines="None" runat="server">
    <Columns>
        <asp:BoundField HeaderText="Id" DataField="Id" />
        <asp:BoundField HeaderText="Title" DataField="Title" />
        <asp:TemplateField HeaderText="Text">
            <ItemTemplate>
                <asp:Literal ID="litCountWords" runat="server" />
                Wörter und <asp:Literal ID="litCountWordsDisplayed" runat="server" />
                 werden angezeigt.
                 <asp:Panel ID="container" runat="server" style="border: 1px solid gray; padding: 4px; margin: 4px;">
                    <asp:Literal ID="litText" runat="server" />
                 </asp:Panel>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Hierbei werden ein paar Controls platziert und eine eindeutige ID vergeben.
Da diese Templates MultipleTemplateInstances sind, werden die IDs automatisch einzigartig gehalten.
Nachteil dabei ist, das nur noch der indirekte Zugriff per <Control>.FindControl() möglich ist. Bei SingleInstence Templates ist der Zugriff direkt über die ID möglich.

Siehe: http://www.nikhilk.net/SingleInstanceTemplates.aspx

Durch eine relativ einfach Manipulation kann der Inhalt bereitgestellt werden:



/// <summary>
/// Wertet den Inhalt aus
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void grdTest2_RowDataBound(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.DataRow) {
        e.Row.Cells[2].CssClass = "fixedWidth";

        Literal countWords = e.Row.FindControl("litCountWords") as Literal;
        Literal countWordsDisplayed = e.Row.FindControl("litCountWordsDisplayed") as Literal;

        Literal text = e.Row.FindControl("litText") as Literal;

        string content = DataBinder.Eval(e.Row.DataItem, "Text").ToString();
        text.Text = Tools.WordWrap(content, 25) + "...";

        countWords.Text = content.Split(' ').Length.ToString();
        countWordsDisplayed.Text = text.Text.Split(' ').Length.ToString();
    }
}

Die Beispielanwendung könnt ihr hier Downloaden:

Referenzen:

Veröffentlicht Montag, 19. Mai 2008 23:05 von Peter Bucher

Kommentare

# re: Ausgabe eines GridViews verändern - DataBound und RowDataBound Events

Hey Peter,

wieder mal top, wie immer ;-)

Vielen Dank für diese Ausführliche Erläuterung.

An Hand deines "Priority" Beispiels habe ich Daten in einem GridView angepasst. Ich habe einfach Nullen am Ende von Daten gelöscht und den neuen Wert als Wert des Feldes gesetzt. Da sich auf der Seite aber noch weiter Panel und Formulare befinden, habe ich das Problem, dass bei einem Klick auf einen Button auf der Page ein Postback stattfindet und der Gridview in den 2 manipulierten Spalten die Werte verliert. Klicke ich dann auf den Gridview um so sortieren, oder auf den Pager, werden die Daten wieder richtig angezeigt. Welchen Event, oder was muss ich aufrufen/tun, damit dies nicht geschieht?

Danke und Grüße

Chester

Freitag, 9. September 2011 15:20 by chester

# re: Ausgabe eines GridViews verändern - DataBound und RowDataBound Events

Hi Peter,

ich nochmal ;-)

Fehler behoben, beim Postback einfach nochmal die bind Methode des GridViews aufrufen....

Danke nochmal

Freitag, 9. September 2011 15:24 by chester
Anonyme Kommentare sind nicht zugelassen