How to format each GridView row based on data-item

Every now and then, someone requests that a html table with should somehow be customised based on data shown, for eg. each row should have different background color for each „Status” column in data-item. In my knowledge there is no easy way of doing it declarative in ASP.NET using standard controls for eg. by data binding RowStyle-CssClass, strange that MS did never thought about such a simple feature.

Here an example how you can add support for row-by-row styling, after you select an appropriate column, just add css style for each possible data value.

/* Copyright 2007 Janusz Skonieczny
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Created by: Janusz Skonieczny 2006-06-02
 *
 * Last changes made by:
 * $Id: $
 */

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using Qualent.Common;

namespace WooYek.Web.UI.WebControls {
    /// <summary>
    /// A simple <see cref="GridView"/> override that adds support to declarative chose a data item column values
    /// that will be used as a CssClass for each <see cref="GridViewRow"/>.
    /// </summary>
    [ToolboxData("<{0}:StyledGridView runat=server></{0}:StyledGridView>")]
    public class StyledGridView : GridView {
        ///<summary>
        ///Raises the <see cref="E:System.Web.UI.WebControls.GridView.RowDataBound"></see> event.
        ///</summary>
        ///
        ///<param name="e">A <see cref="T:System.Web.UI.WebControls.GridViewRowEventArgs"></see> that contains event data.</param>
        protected override void OnRowDataBound(GridViewRowEventArgs e) {
            base.OnRowDataBound(e);
            FillCssClass(e);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="e"></param>
        private void FillCssClass(GridViewRowEventArgs e) {
            string cssClassColumnName = CssClassColumnName;
            if (!String.IsNullOrEmpty(cssClassColumnName) && e.Row.RowType == DataControlRowType.DataRow) {
                object dataItem = e.Row.DataItem;
                Guard.NotNull(dataItem, "dataItem", "Given dataItem is null");
                object eval = DataBinder.Eval(dataItem, cssClassColumnName);
                if (eval == null) {
                    throw new InvalidOperationException("There is no data in dataItem for member " + cssClassColumnName);
                }
                e.Row.CssClass = eval.ToString();
            }
        }

        public string CssClassColumnName {
            get { return (string) ViewState["CssClassColumnName"]; }
            set { ViewState["CssClassColumnName"] = value; }
        }
    }
}

An exmaple of page (control is registered in web.config)

<%@ Page Language="C#" MasterPageFile="~/Default.master" AutoEventWireup="true" CodeFile="CustomerList.aspx.cs" Inherits="web_CusomerList" Title="Customer List" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" CancelSelectOnNullParameter="false" ConnectionString="<%$ ConnectionStrings:Default %>" SelectCommand="SELECT * FROM [vCustomer]">
    </asp:SqlDataSource>
    <wc:StyledGridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CustomerId" DataSourceID="SqlDataSource1" CssClassColumnName="CustomerStatusName">
        <Columns>
            <asp:BoundField DataField="CustomerId" HeaderText="ID" ReadOnly="True" SortExpression="CustomerId" />
            <asp:HyperLinkField DataTextField="CustomerName" HeaderText="Nazwa" SortExpression="CustomerName" DataNavigateUrlFields="CustomerId" DataNavigateUrlFormatString="CustomerDetails.aspx?CustomerId={0}" />
            <asp:BoundField DataField="CustomerStatusName" HeaderText="Status" ReadOnly="True" SortExpression="CustomerStatusName" />
        </Columns>
    </wc:StyledGridView>
</asp:Content>

And here an example of CSS class you could use.

tr.StatusNew {
    background-color: #efffb5;
}

tr.StatusArchive {
    background-color: #ccff33;
}

Dodaj komentarz