Library tutorials & articles

Building a Full-Featured Custom DataGrid Control

Now We Compile...

Till now, most of the key elements in our DLL have been grappled with. Now we finalize our application by compiling it and then importing it into our page thus rounding off everything full circle.

Anytime you create a class of any kind that requires implementation within your page it first needs to be compiled, and placed into your applications bin, or wwwroot\inetpub\bin folder. Since our classes language is C#, we use the .NET C# compiler from a command line like so, or typed into a .bat batch file (which is included in this article's source code as makedg.bat):

csc /t:library /out:bin\mycustDG.dll mycustDG.cs /optimize

This tells our compiler that we are going to create a DLL named mycustdg using mycustDG.cs as the source file. /t imports all pertinent namespaces used in our control and /optimize optimizes our DLL for more efficiency.

Note: By default, .NET v1.1 may not have added the compiler's path to your environment variables. Therefore running this command line utility may not work as listed. To remedy this, add "%SystemRoot%\Microsoft.NET\Framework\v1.1.4322" to your System's Path Environment Variables, via Control Panel > System > Advanced > Environment Variables > System Variables > Path. Edit this variable, and append the aforementioned value to it. This way you could now execute any of the compilers anywhere without having to specify any full paths.

Now, once we've compiled our assembly, we import it at the top of our page using the @Register directive, like so, in conjunction to our custom Datagrid control tag above:

<%@ Register TagPrefix="DMGrid" Namespace="CustDataGrid" Assembly="myCustDG" %>

and when we setup our custom Datagrid we get the results that were shown in the image at the beginning of this article, and that's it!

As for VS.NET users, I have included the entire example as a VS.NET project in C# for download. All you need to do is create a new C# Web Application Project, compile the C# source file as a dll as mentioned, and reference it into to your project solution via Add New Reference.

To make it even easier for you, simply download the VS.NET Project code, as it contains everything I just mentioned. Now extract it into a folder named CustomDatagrid within wwwroot/inetpub, and simply double click the CustomDatagrid.sln file and voila.

The complete C# standard .NET page code:

<%@ Page language="C#" Inherits="CustDG.WebForm" Src="datagrid.aspx.cs" Debug="False" Explicit="True" Strict="True" Buffer="True" Trace="False" EnableSessionState="True" %>
<%@ Register TagPrefix="DMGrid" Namespace="CustDataGrid" Assembly="myCustDG" %>
<HTML>
<BODY onLoad="txtFocus();">
<BR>
<H2>Cached Custom Datagrid Control Class</H2>
    <form runat="server">
        <br>
        <asp:textbox id="srchTxt" runat="server" />
        <asp:button text="Search" id="Search" OnTextChanged="Rebind_Grid" AutoPostBack="True" runat="server" />
        <asp:button text="Reset" name="Reset" onClick="Reset_Grid" runat="server" />
        <BR><BR>
        <asp:label id="Stats" runat="server" />
        <BR><BR>
        <DMGrid:myCustDG ID="MyDataGrid" runat="server" autoCols="true" bgClr="Red" frClr="White" />
    </form>
</BODY>
</HTML>

And for all you VS.NET programmers, here is the VS C#.NET Project Solution - the .aspx page

<%@ Page language="C#" Inherits="CustDG.WebForm" Codebehind="datagrid.aspx.cs" Debug="False" Explicit="True" Strict="True" Buffer="True" Trace="False" EnableSessionState="True" %>
<%@ Register TagPrefix="DMGrid" Namespace="CustDataGrid" Assembly="myCustDG" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    <HEAD>
        <title>Custom Datagrid Control</title>
        <%-- datagrid.aspx.cs contains our methods that interact with and control our Datagrid's functionality on this page --%>
        <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <meta content="C#" name="CODE_LANGUAGE">
        <meta content="JavaScript" name="vs_defaultClientScript">
        <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    </HEAD>
    <body onload="txtFocus();" MS_POSITIONING="GridLayout">
    <BR>
    <H2>Cached Custom Datagrid Control Class</H2>
    <form id="Form1" method="post" runat="server">
        <br>
        <asp:textbox id="srchTxt" runat="server" />
        <asp:button id="Search" onclick="Rebind_Grid" runat="server" text="Search" />
        <asp:button id="Reset" onclick="Reset_Grid" runat="server" text="Reset" />
        <BR><BR>
        <asp:label id="Stats" runat="server" />
        <BR><BR>
        <DMGrid:myCustDG ID="MyDataGrid" runat="server" autoCols="true" bgClr="Red" frClr="White" />
    </form>
    </body>
</HTML>

Below now I'll list the Code-Behind code applicable to both standard ASP.NET and Visual C#.NET applications. The only difference between the two is in the way each platform references the code-behind file. Both reference this file within their respective @Page Directives, however our standard C# page needs to reference this code with the "Src= file location" attribute, whereas VS.NET uses "Codebehind= file location" attribute.

//datagrid.aspx.cs Code-Behind Page
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
//Import mycustDG dll namespace so this code-behind page can access our custom Datagrid control on the main page.
using CustDataGrid;
namespace CustDG
{
    public class WebForm : System.Web.UI.Page //Inherit Page Class
    {
        protected System.Web.UI.WebControls.TextBox srchTxt;
        protected System.Web.UI.WebControls.Button Search;
        protected System.Web.UI.WebControls.Button Button1;
        protected System.Web.UI.WebControls.Label Stats;
        // Declare myDatagrid as myCustDG from referenced dll to allow code-behind Datagrid interaction with main Page Datagrid control properties
        public myCustDG MyDataGrid;

        public void Page_Load (Object Sender, EventArgs E)
        {

       //Implement Client Side JavaScript code
        StringBuilder jsScript = new StringBuilder();
        string nl = Environment.NewLine;        

        jsScript.Append ("<script language=JavaScript>" + nl);
        jsScript.Append ("<!--" + nl);
        jsScript.Append ("var isIE; " + nl);
        jsScript.Append ("if (navigator.appName == \"Microsoft Internet Explorer\"){isIE = true;} " + nl);
        jsScript.Append (" " + nl);
        jsScript.Append ("function getButton() " + nl);
        jsScript.Append ("{ " + nl);
        jsScript.Append (" //Capture Netscape events " + nl);
        jsScript.Append (" if(!isIE) { " + nl);
        jsScript.Append (" document.captureEvents(Event.KEYDOWN); " + nl);
        jsScript.Append (" } " + nl);
        jsScript.Append (" document.onkeydown = submitText" + nl);
        jsScript.Append ("} \n" + nl);
        jsScript.Append ("function submitText(evt){ \n" + nl);
        jsScript.Append (" var theButtonPressed; \n" + nl);
        jsScript.Append (" if (isIE){ " + nl);
        jsScript.Append (" theButtonPressed = window.event.keyCode; " + nl);
        jsScript.Append (" }else{ " + nl);
        jsScript.Append (" theButtonPressed = evt.which; " + nl);
        jsScript.Append (" } \n" + nl);
        jsScript.Append (" if (theButtonPressed == 13) { \n" + nl);
        jsScript.Append (" if(isIE){ " + nl);
        jsScript.Append (" with(event){ " + nl);
        jsScript.Append (" cancelBubble = true; " + nl);
        jsScript.Append (" returnValue = false; " + nl);
        jsScript.Append (" } " + nl);
        jsScript.Append (" } \n" + nl);
        jsScript.Append (" document.getElementById(\"Search\").click(); " + nl);
        jsScript.Append (" } " + nl);
        jsScript.Append ("} \n" + nl);
        jsScript.Append ("function txtFocus(){ \n" + nl);
        jsScript.Append (" with (document.getElementById(\"srchTxt\")){ " + nl);
        jsScript.Append (" focus(); " + nl);
        jsScript.Append (" select(); " + nl);
        jsScript.Append (" } \n" + nl);
        jsScript.Append ("} \n" + nl);
        jsScript.Append ("//--> " + nl);
        jsScript.Append ("</script>" + nl);

        //Allows our .NET page to add client-side script blocks when page loads, instead of the conventional HTML JS tags.
       RegisterClientScriptBlock("clientScript", jsScript.ToString());
       //Close our StringBuilder Object
        jsScript = null;

       srchTxt.Attributes.Add("onkeydown", "getButton();");
        Response.BufferOutput = true;       
            if (Page.IsPostBack)
            {
                //Set up our database connection string<
               MyDataGrid.strConn="server=(local);uid=sa;pwd=;database=Northwind;";
                MyDataGrid.Visible = true;
                MyDataGrid.autoCols = true;
                GridAction ();
            }
            //Response.Flush();
        }

        public void Rebind_Grid (Object Sender, EventArgs E)
        {
            HttpContext.Current.Session.Remove("dgCache"); //Remove session value to create new one before rebinding
            //HttpContext.Current.Cache.Remove("dgCache"); //Remove cache to create new one before rebinding
            Stats.Visible = true;
            MyDataGrid.CurrentPageIndex = 0;
            GridAction ();
        }

        public void GridAction ()
        {
            MyDataGrid.sqlQuery = "SELECT SupplierID As No, CompanyName, ContactName, Country FROM Suppliers where CompanyName like '%" + srchTxt.Text + "%' or ContactName like '%" + srchTxt.Text + "%' or Country like '%" + srchTxt.Text + "%' Order by CompanyName asc";
            MyDataGrid.GetDataGrid(); //Rebind Grid
        }

        public void Reset_Grid (Object Sender, EventArgs E)
        {
            HttpContext.Current.Session.RemoveAll(); //Remove session value to create new one before rebinding
            //HttpContext.Current.Cache.Remove("dgCache"); //Remove cache to create new one before rebinding
            srchTxt.Text = "";
            Stats.Visible = false;
            MyDataGrid.CurrentPageIndex = 0;
            MyDataGrid.Visible = false;
        }
    } // End Class
} //End Namespace

And the complete C# class source code for our compiled myCustDG dll used in our @Register Directive and referenced in our VS.NET project:

//C# - mycustDG.cs - Written by Dimitrios Markatos, 2003
using System.Reflection; //For assembly information attributes
[assembly: AssemblyTitle("Custom DataGrid Control")]
[assembly: AssemblyDescription("Pageable, Cacheable Datagrid Custom Control Class")]
[assembly: AssemblyCopyright("Dimitrios Markatos [dmarko1@aol.com] - 2003")]
namespace CustDataGrid
{
    /// <summary>
    /// Custom Datagrid Control Class
    /// Author: Dimitrios Markatos - dmarko1@aol.com
    /// Date: 5/22/2003
    /// </summary>
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Diagnostics; //For Tracing
    using System.Drawing; // For Datagrid Colors
    using System.Web; // For HttpContext
    using System.Web.SessionState; // For HttpSessionState
    using System.Web.UI; //For Literal Controls
    using System.Web.UI.WebControls; // For Datagrid

    public class myCustDG : DataGrid
    { //Inherits the DataGrid Class
        // Internal private variables
        protected DataGrid MyDataGrid;
        protected DataSet objDS, dgCache;
        protected SqlConnection objConnect;
        protected SqlDataAdapter objDataAdapter;
        private bool _autoCols;
        private string _strConn, _sqlQuery;
        private Color _bgClr, _frClr;
        private int RcdCount, StartCnt, EndCnt; //_pageSz,
        int _bWidth = 0;
        //Allow external access to variables

        // DataGrid Set properties that get parameters from external control on page
        public string strConn
        {
            get { return _strConn; }
            set { _strConn = value; }
        }
        public bool autoCols
        {
            get { return _autoCols; }
            set { _autoCols = value; }
        }
        public string sqlQuery
        {
            get { return _sqlQuery; }
            set { _sqlQuery = value; }
        }

        public int bWidth
        {
            get { return _bWidth; }
            set { _bWidth = value; }
        }

        public Color bgClr
        {
            get { return _bgClr; }
            set { _bgClr = value; }
        }

        public Color frClr
        {
            get { return _frClr; }
            set { _frClr = value; }
        }

        protected override void OnPreRender(EventArgs e)
        {
            Control StatsCtrl = Page.FindControl("Stats");
            if (StatsCtrl != null)
            {
                if (Page.IsPostBack)
                {
                    if (RcdCount == 0)
                    {
                        StatsCtrl.Controls.Add(new LiteralControl("<font size=2><b>No Records Found</b></font>"));
                        Visible = false;
                    }
                    else
                    {
                        StatsCtrl.Controls.Add(new LiteralControl("<font size=2><b>Your search for <font color=red> " + HttpContext.Current.Request ["srchTxt"] + " </font>found " + RcdCount + " records / " + PageCount + " pages<BR>Results No. " + StartCnt + " to " + EndCnt + " / Page " + (CurrentPageIndex+1) + " of " + PageCount + "</b></font>"));
                        Visible = true;
                    }
                }
            }
        }

        public void GetDataGrid()
        {
            PageSize = 5;
            AutoGenerateColumns = autoCols;
            AllowPaging = true;
            GridLines = GridLines.None;
            BorderWidth = bWidth;
            BorderColor = Color.Black;
            ShowFooter = true;
            CellPadding = 3;
            CellSpacing = 0;
            Font.Name = "Verdana, Helvetica";
            Font.Bold = true;
            Font.Size = FontUnit.XXSmall;
            Width = 500;

            // Header Setting
            HeaderStyle.Font.Bold = true;
            HeaderStyle.BackColor = bgClr;
            HeaderStyle.ForeColor = frClr;
            HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
            // Pagerstyle settings
            PagerStyle.Mode = PagerMode.NumericPages;
            PagerStyle.BackColor = Color.Gainsboro;
            PagerStyle.PageButtonCount = 10;
            PagerStyle.Font.Size = FontUnit.XSmall;
            PagerStyle.HorizontalAlign = HorizontalAlign.Right;
            DataSource = GridCachedData();

            try
            {
                DataBind();
            }
            catch
            {
                CurrentPageIndex = 0; //to catch any errors
            }
            PageIndexChanged += new DataGridPageChangedEventHandler (PageChanged);
            ItemCreated += new DataGridItemEventHandler (GridCreated);
            //Tracing inside a component
            // HttpContext.Current.Trace.Write ("Datagrid");
        }
        private DataSet GridCachedData()
        {
            //DataSet dgCache = (DataSet) HttpContext.Current.Cache.Get("dgCache");
            DataSet dgCache = (DataSet) HttpContext.Current.Session["dgCache"];
            if (dgCache == null)
            {
                SqlConnection objConnect = new SqlConnection(strConn);
                SqlDataAdapter objDataAdapter = new SqlDataAdapter (sqlQuery.ToString(), objConnect);
                DataSet objDS = new DataSet();
                //Create DataTable
                objDataAdapter.Fill (objDS);

                HttpContext.Current.Session.Add ("dgCache" ,objDS); // Session way
                //HttpContext.Current.Cache.Insert("dgCache", objDS, null,
                DateTime.Now.AddMinutes(10), TimeSpan.Zero); // Caching way
                RcdCount = objDS.Tables[0].Rows.Count;
                return objDS;
            }
            else
            {
                RcdCount = dgCache.Tables[0].Rows.Count;
                return dgCache;
            }
        }
        //Paging
        protected void PageChanged(Object sender, DataGridPageChangedEventArgs e)
        {
            CurrentPageIndex = e.NewPageIndex;
            GetDataGrid();
        }

        private void GridCreated(Object sender, DataGridItemEventArgs e)
        {

            //Declare the ItemType
            ListItemType elemType = e.Item.ItemType;

            if (elemType == ListItemType.Item || elemType == ListItemType.AlternatingItem)
            {
                //A DataGrid Item represents an item (row) in the DataGrid control
                //e.Item is the table row where the command is raised
                DataGridItem dgRow = (DataGridItem) e.Item;
                int rowCntIncr = dgRow.DataSetIndex + 1; //Gets the index number of the DataGridItem object from the bound data source
                //Get the start and end index count from datagrid
                //declare as typed variables first then convert
                StartCnt = rowCntIncr-dgRow.ItemIndex;
                EndCnt = rowCntIncr;
            }
        }

    } // End Class
} // End NameSpace

Comments

  1. 09 Oct 2006 at 13:32
    Hi,
    I am building a ASP .NET composite control containing a datagrid during which I am 
    finding a problem while paging of the grid.

    The problem is for example if I am having three pages to be displayed in the
    datagrid, I have set the paging mode to be numeric.Now I am going to have
    1,2,3 for navigation.
    All navigations are working perfectly but when I go back to page 1 after page 2
    or 3, the PageIndexChanged event is not triggered and I happen to see only the
    information of previous page (i.e page 2 or page 3).



    Thanks in Advance
    Ashish

















  2. 02 Feb 2006 at 08:16

    I build my own custom datagrid control using the code from your site.


    I used this control as a reference in another aspx page at you have mentioned in your article.
    I have 400 total number of records and my page count is 5. I wrote a stored procedure which will fetch 10 records each time for custom paging.


    When I click on ellipse after 5 it shoud page 6 to 10 but they link to first set of pages. So when I click on 6 it takes me to page 1 and so on. I am unable to navigate to more than 5 pages....


    Please Let me know...

  3. 22 Dec 2005 at 15:23

    Quote:
    [1]Posted by taxiturner on 3 May 2005 10:25 PM[/1]
    LiteralControl lc = (LiteralControl) sender;
    DataGridItem container = (DataGridItem) lc.NamingContainer;
    lc.Text = ((DataRowView) container.DataItem) [columnName].ToString();




    I believe that "container" is your problem.
    try:


    lc.Text = ((DataRowView)e.Item.DataItem)[columnName].ToString();



    Now, if someone could just tell me how to cast a DataGridItemCollection as a TableRowCollection so that I don't get this error, that would be helpful.

  4. 22 Nov 2005 at 11:21

    I have created a Custom control using your article but i am having problem in sorting and update
    as i use a class which implements itemplate interface  for this and create the function for update and
    sorting  in same class.when i click on them the changes are made in database and dataset but they does not display on page and display on second click as these function are called in last i.e the getdatagrid() method is not called after them hence no changes are viewed.Please help me to resolve this problem.Can i use ipostbackdatahandler.


    Thanks in Advance

  5. 31 Oct 2005 at 06:32

    There will be some 20 questions and  for each question there will be  4 choices.what i want to do is to select multiple answers by clicking the checkbox. i m using asp.net,vb.net
    pls help me


    we have written the code using radio button for selecting single item.but we  want to replace it with checkbox to select multiple items. the code using radio button is given below .pls correct it with checkbox


    Imports System.Data
    Imports System.Data.SqlClient
    Imports ELearning.LAIDBC
    Public Class Test
      Inherits System.Web.UI.Page
      Public ds As New DataSet()
      Public ds1 As New DataSet()
      Public ds2 As New DataSet()
      Public Score, Answered As Integer
      Protected WithEvents txtNoOfqns As System.Web.UI.WebControls.TextBox

    Region " Web Form Designer Generated Code "



      'This call is required by the Web Form Designer.
      <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()


      End Sub


      Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
          'CODEGEN: This method call is required by the Web Form Designer
          'Do not modify it using the code editor.
          InitializeComponent()
      End Sub
      Protected WithEvents lblCourse As System.Web.UI.WebControls.Label
      Protected WithEvents lblCourseName As System.Web.UI.WebControls.Label
      Protected WithEvents lblNoOfQuestions As System.Web.UI.WebControls.Label
      Protected WithEvents lblDurationInMinutes As System.Web.UI.WebControls.Label
      Protected WithEvents txtduration As System.Web.UI.WebControls.TextBox
      Protected WithEvents lblTimeLeft As System.Web.UI.WebControls.Label
      Protected WithEvents lblAnswered As System.Web.UI.WebControls.Label
      Protected WithEvents txtanswered As System.Web.UI.WebControls.TextBox
      Protected WithEvents DataGrid1 As System.Web.UI.WebControls.DataGrid
      Protected WithEvents submitbtn As System.Web.UI.WebControls.Button
      Protected WithEvents lab2 As System.Web.UI.WebControls.Label
      Protected WithEvents Lab4 As System.Web.UI.WebControls.Label
      Protected WithEvents Label2 As System.Web.UI.WebControls.Label
      Protected WithEvents lab1 As System.Web.UI.WebControls.Label
      Protected WithEvents txtans As System.Web.UI.WebControls.TextBox


    End Region


      Private ConDB As New ELearning.LAIDBC()
      Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
          If Session("Log") = Nothing Then
              Response.Redirect("frmLogin.aspx")
          End If


          If Not IsPostBack Then


              Try
                  Session("Course") = Session("URL2")
                  Session("Id") = "reshm-001"
                  Session("CandId") = "00000001"
                  'Response.Write(Session("Id"))
                  'Response.End()
                  Session("TotScore") = Nothing
                  Dim count1, str11 As String
                  ds1 = New DataSet()
                  ConDB.OpenConnection()


                  ds1 = ConDB.ExecuteSPReturnDS("ELSExecuteQuery", "select count(fUserId) from tblScore where fUserId='" & (Session("CandId")) & "'  and  fcourseid='" & Session("Id") & "' ")
                  ConDB.CloseConnection()
                  count1 = ds1.Tables(0).Rows(0)(0)
                  str11 = "select count(f
    UserId) from tblScore where fUserId='" & (Session("CandId")) & "'  and  fcourseid='" & Session("Id") & "'"
                  'Response.Write(str11)
                  'Response.End()
                  If count1 < 3 Then
                      ' Response.Write(str11 & "," & count1)
                      ds2 = New DataSet()
                      Dim count2 As Integer
                      ConDB.OpenConnection()
                      ds2 = ConDB.ExecuteSPReturnDS("ELS
    ExecuteQuery", "select count(fUserId) from tblScore where fUserId='" & (Session("CandId")) & "' and fresult='P'")
                      count2 = ds2.Tables(0).Rows(0)(0)
                      Response.Write(count2)
                      ConDB.CloseConnection()
                      If count2 > 0 Then


                          Session("msg") = "You have already passed for the test"
                          Response.Redirect("frmChance.aspx")
                      Else
                          Dim qrstr As String
                          Dim NoOfQuestionsToDisplay As Integer
                          Dim Mstring As String
                          Dim TotalNoOfQuestions As Integer
                          courseidselect()
                          Try
                              NoOfQuestionsToDisplay = txtNoOfqns.Text
                              Session("NoOfQuestionsToDisplay ") = txtNoOfqns.Text
                              ds = New DataSet()
                              ConDB.OpenConnection()
                              ds = ConDB.ExecuteSPReturnDS("ELSExecuteQuery", "select  count(*)  from tblQuestion where f_CourseId='" & Session("Id") & "'")
                              ConDB.CloseConnection()
                              TotalNoOfQuestions = ds.Tables(0).Rows(0)(0)
                              Session("TotQns") = TotalNoOfQuestions
                          Catch ex As Exception
                              R

  6. 05 Sep 2005 at 09:32
    I am having a datagrid where i am binding all boundcolumns from dataset and along with it i am having 2 templates , one is label and another checkbox . these two controls are bound to datagrid using itemplate class (i.e. dynamically) . when i am attaching checkbox and allocating event checkedchanged , its not getting fired and also i am unable to get how many checkbox are clicked (if autopostback=false) . if autopostback is true then datagrid is not displayed but if i again bind datagrid with all bouncontrols usinf sessions then i get same old datagrid but all checkbox are false .

    I hope i am clear with my problem . please help me in getting event fired for checkbox and also getting count for number of check box clicked .

    Thanks in advance,
    Rujuta
  7. 15 Jul 2005 at 16:25
    Hi,

    You can implement one way as found in my other article here on DF - Dynamic Column Sorting and Paging in ASP.NET or you can download the upgraded version of my custom datagrid control with drag and drop columns and sorting.

    -Jimmy Markatos
  8. 14 Jul 2005 at 04:53

    how can i implement sorting for all the column in this sample?

  9. 23 Jun 2005 at 22:19
    I'm having the same problem.  Please let me know if you find anything.
  10. 13 Jun 2005 at 15:37

    Hi all,


    I just re-added the forum post containing the new version of my article code. I just thought it easier to repost it again, since I find people requesting this and since the topics become hidden after a while, it won't show up unless you select all topics.


    Anyway, here is the link:


    Custom DG Ctrl w/ Dual Paging, Drag&Drop/Sort DL code forum post


    -Jimmy Markatos

  11. 06 Jun 2005 at 19:07

    Right, I misunderstood you, as I was referring to DataSet data and I simply specified if you explicitly disabled view state, as yes, of course, true is the default. Now if you utilize what else I've mentioned then you shouldn’t have any issues.


    Also, I don't know what you mean with 2 other grids that maintain state. Are they all the same with dynamic item templates and all? As I can’t see your code I don’t know what you may have overlooked or otherwise.


    Therefore, employ the Page_Init method to help with this, but ultimately whenever something doesn't hold state by normal means as you would’ve hope it would then make use of view state.


    Hope this helps.

  12. 06 Jun 2005 at 17:04

    I read this article on msdn:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuiwebcontrolsdatagridcolumncollectionclasstopic.asp


    It seems to say that derived coumns (from say itemtemplate) that are added at run time are not saved to view state.


    They suggest having all needed cols and set visible attribute of those not needed for display to be set to false.


    I do have the EnableViewState=true (I think that is the default) on the page and grid.  I have 2 other grids that do maintain the state...


    -anabhra

  13. 06 Jun 2005 at 16:59

    Yes, becuase by default all data within a DataSet is typically persisted in ViewState. Have you explcitly disabled Page ViewState? I don't see how your dynamically sized columns would reset themselves.


    At any rate, try enabling the DataGrid's DataGrid.EnableViewState property to true to maintains its state across HTTP requests.


    Furthermore, you can ideally stored any values you require to be persistant by storing those values in Session State.


    This should take care of it.


    - Jimmy Markatos

  14. 06 Jun 2005 at 16:06

    I have one more question:


    When using template columns dynamically, are they stored in the view state?
    It seems not but I would like to have them as I have editable text boxes in the template columns that user enters data in...


    Many thanks,
    anabhra

  15. 02 Jun 2005 at 20:26
    You're welcome. Glad to help!
  16. 02 Jun 2005 at 20:23
    thanks a lot.

    your suggestion will work.

    I just solved my problem by setting the header template and itemtemplate widths. I had the grid in a div and that is why I could not see the widths. Once I set the table layout of the grid to fixed, I saw the columns being sized.

    again, many thanks for your interest.
  17. 02 Jun 2005 at 20:20
    Sure, just add your datagrid column modifications in the ItemCreated event handler.

    Ex. in Pixels:
    Code:
    'VB
    Private Sub GridCreated (ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles GridCreated
      e.Item.Cells(0).Width = New Unit (100, UnitType.Pixel)
      e.Item.Cells(1).Width = New Unit (75, UnitType.Pixel)
    End Sub

    //C#
    private void GridCreated (object sender, DataGridItemEventArgs e)
    {
      e.Item.Cells[0].Width = new Unit (100, UnitType.Pixel);
      e.Item.Cells[1].Width = new Unit (75, UnitType.Pixel);
    }

    Furthermore, you can accomodate other Unit structures such as Percentage.

    Ex. in Percentage:
    Code:
    'VB
    Private Sub GridCreated (ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles GridCreated
      e.Item.Cells(0).Width = New Unit (50, UnitType.Percentage)
      e.Item.Cells(1).Width = New Unit (25, UnitType.Percentage)
       End Sub

    //C#
    private void GridCreated (object sender, DataGridItemEventArgs e)
    {
      e.Item.Cells[0].Width = new Unit (50, UnitType.Percentage);
      e.Item.Cells[1].Width = new Unit (25, UnitType.Percentage);
    }


    Hope this helps.

    - Jimmy Markatos
  18. 02 Jun 2005 at 18:12
    I am dynamically creating/adding template columns to my datagrid. (implementing ITemplate interface).

    However, I am unable to set the width of this dynamically added column.

    any ideas?

    Many thanks,
    anabhra
  19. 17 May 2005 at 19:48

    Glad to help!

  20. 16 May 2005 at 21:50

    Excellent!

  21. 16 May 2005 at 21:10

    Sure. You'll notice in my article's datagrid enhancements section How to customize the Datagrid pager, I show one way of manipulating the pager to which CSS could easily be added.


    Furthermore, in the article's forum post  I offer an improved version of my custom datagrid control, where I have added onmouseover rowhighlighting which further demonstrates CSS enhancement.


    Essentially, in modifying any elements of the datagrid, you’ll need to work with the grid’s OnItemCreated or OnItemDataBound methods to include any grid manipulations.


    Example:


    Your stylesheet:


    Code:
    <style>
    .DGPager {font-family: garamond; font-size:16px;}
    .DGPager a:link {font-size:16px; color:#0000FF;}
    .DGPager a:visited {font-size:16px; color:#C0C0C0;}
    .DGPager a:hover {font-size:16px; color:#FF0000;}
    </style>

    Next, add the event handler to your datagrid to call the method


    Code:
    OnItemCreated="Item_Created"

    And in the OnItemCreated method or in my article's GridCreated method, you add the following code in your code-behind or in your main page which determines you want to deal with the datagrid’s pager. The same goes for the header:
    Code:
    if (elemType == ListItemType.Pager) {


       e.Item.Cells[0].Attributes.Add("class","DGPager");


    }


    and for you in VB:


    Code:
    If (e.Item.ItemType = ListItemType.Pager) Then


       e.Item.Cells(0).Attributes.Add("class","DGPager")


    End If


    That’s it.


    -Jimmy Markatos

  22. 16 May 2005 at 19:21

    Thanks- this seems to be a different approach.  I haven't looked at it in detail, but am interested.  It's interesting that the DataGrid with Month Pager Tabs was based on an article Dino wrote in ASP.Net Pro, and he also wrote the other 2 on editing the header, which I got to work, and on freezing the header, which I could not get to work (all of his samples in ASP.Net Pro are in C#, and I am still using VB, so I'm forced to use a translator which doesn't alway work.  They have just changed their policy to include both C# and VB, which is the best way to learn either in my opinion).


    Thanks for the help.  Do you know of any examples where the Pager can be manipulated with CSS?  

  23. 16 May 2005 at 18:57

    Thanks stevemets,


    What you need is a custom pager control to give you the ability to provide fixed paging. I believe what you're looking for can be found here - Creating a Pager Control for ASP.NET by Dino Esposito.


    Hope this helps!

  24. 15 May 2005 at 01:44

    Your Datagrid is very useful.  I have built a custom DG with paging set for Months (Jan-Dec) which serves up the sales for the month selected in the Pager Tab.  I have also enabled both Header Editing and Freezing Header as you scroll.  What I have not been able to do is to allow the Pager control to freeze in a similar manner as you scroll- the goal being to have the Header and Pager Tabs always visible so you don't have to go back to the top to change selection or remember what the data is in which column.  In general, I have not been able to apply any formatting using CSS to the pager at all.  Any help would be appreciated.


    Thanks!

  25. 13 May 2005 at 14:26
    Cool, thanks. Glad to see it's helped you out.
  26. 09 May 2005 at 22:01
    Will take another look.

    Many thanks for your reply.

    Sean.
  27. 09 May 2005 at 20:51
    In order for those events to fire, you have to re-create the same controls when the page is reloaded. The DataGrid does this by using it's ViewState to restore the data it was originally bound to, and hence recreating all the rows in the table. You'd therefore have to do a similar trick of storing the data in the ViewState, and rebinding to that if DataBind() isn't called.
  28. 09 May 2005 at 17:02
    I wrote my own custom datagrid a short time ago, and included code that automatically handled the pageindexchanged and itemdatabound events. The upshot was that I could not get the code to run unless I re-bound the control on every page load.

    Is this normal?
    Conventional datagrids do not require this. What could I have been doing wrong?
    What are the issues with auto handling events with custom controls?

    many thanks
    Sean.
  29. 03 May 2005 at 22:25

    Doing someting similar to the code in the posting for "Building a Full-Featured Custom DataGrid Control" using datagrids and having a duece of a time getting past one problem.  
    The error encountered is System.InvalidCastException: Specified cast is not valid. I'm using the same code as up above for setting up the databinding for an item template in a datagrid. If I use a control file I have no problems with binding the data (from my SQL Server database).  But for some reason I can't assign the databinding using a code behind file .  Here's the code, just like up above as far as I can tell.


    LiteralControl lc = (LiteralControl) sender;
    DataGridItem container = (DataGridItem) lc.NamingContainer;
    lc.Text = ((DataRowView) container.DataItem) [columnName].ToString();


    Again, I have no problems binding to my itemtemplate column using other methods, so I'm wrather sure it's not a data issue.  I have seen mention on MSDN of this type of problem possibly being related to control tree hierarchy being re-ordered at this address http://support.microsoft.com/default.aspx?scid=kb;en-us;Q327287 but I couldn't see how to fix it from what they gave as a solution.  Their solution, to save you the trip, is this:
    "Make sure that the control tree is re-created on postback in the same order that it was saved at the end of the previous request."  My depth of .net knowledge doesn't go that deep.
    Any ideas?


    Thanks.


    Stack trace is here.
    [InvalidCastException: Specified cast is not valid.]
      DataGridTemplate.OnDataBinding(Object sender, EventArgs e) +13
      System.Web.UI.Control.OnDataBinding(EventArgs e) +66
      System.Web.UI.Control.DataBind() +26
      System.Web.UI.Control.DataBind() +86
      System.Web.UI.Control.DataBind() +86
      System.Web.UI.WebControls.DataGrid.CreateItem(Int32 itemIndex, Int32 dataSourceIndex, ListItemType itemType, Boolean dataBind, Object dataItem, DataGridColumn[] columns, TableRowCollection rows, PagedDataSource pagedDataSource) +169
      System.Web.UI.WebControls.DataGrid.CreateControlHierarchy(Boolean useDataSource) +1411
      System.Web.UI.WebControls.BaseDataList.OnDataBinding(EventArgs e) +49
      System.Web.UI.WebControls.BaseDataList.DataBind() +23
      Rock.BudgetDataGrid.datagridSetup(DataGrid datagrid) +914
      ASP.CreateProfilePage4aspx.PageLoad(Object sender, EventArgs e) in \CreateProfilePage4.aspx:28
      System.Web.UI.Control.OnLoad(EventArgs e) +67
      System.Web.UI.Control.LoadRecursive() +35
      System.Web.UI.Page.ProcessRequestMain() +750

  30. 28 Mar 2005 at 00:48

    Hi all,


       I’ve added a newly enhanced version of my Custom Datagrid that adds some cool features and functionality including drag & drop columns that was incorporated from the wonderful article Extend the ASP.NET Datagrid with Client-side Behaviors by Dino Esposito found in the January 2004 issue of MSDN Magazine.


    I merged the code and functionality into the class assembly instead of the two found in the article. So in turn, you now really end with an awesome fully featured custom Datagrid control!


       The features are:
       
       1) Custom Paging taken from my article - Custom ASP.NET DataGrid Paging With Exact Count , alongside the conventional Datagrid paging setup.


       2) Drag & Drop Columns and Sorting from Dino Esposito's article


       3) Adding Background Image to Datagrid Header


       4) OnMouseover Datagrid Row Highlighting


       The only difference from this and my original article and code from "Building a Full-Featured Custom Datagrid Control" aside from the aforementioned, is in the code-behind setup. In this case, the dll class contains the drag & drop code and the Datagrid class only. My code-behind page inherits this and contains all of the remaining code.
       
       Be also sure to check out this article here on developerfusion.com where I have listed four additional Datagrid enhancements that you could incorporate into this Datagrid.


    Download the code here -> http://members.aol.com/dmarko1/dnjcode/CustDGDualPagingDragDrop_Sort.zip


    And feel free to send me an email and tell me what you think -- dmarko1@aol.com


    -Jimmy Markatos

  31. 21 Mar 2005 at 18:23
    Hey folks,

    Here's one quick and easy way to add a background image to your Datagrid header, to give it a more fuller look. The code to do this is:

    Code:
    if (elemType == ListItemType.Header ) {

    e.Item.Style["background-image"] = "url(yourimage.jpg)";

    }


    Simply add this to my article's "myCustDG.cs"  source file code in the "GridCreated" method found at the end, recompile the source code to get your "myCustDG.dll"  and you're done.

    Even easier is my other forum post "Custom DG Control w/ Dual Paging, Drag & Drop/Sort" that has this incorporated into it and a whole lot more and you can download the code with all the enhancements here -> http://members.aol.com/dmarko1/dnjcode/CustDG_DualPaging_DragDrop_Sort.zip

    -Jimmy Markatos
  32. 01 Jan 1999 at 00:00

    This thread is for discussions of Building a Full-Featured Custom DataGrid Control.

Leave a comment

Sign in or Join us (it's free).

Dimitrios Markatos Dimitrios, or Jimmy as his friends call him, is a .NET developer/architect who specializes in Microsoft Technologies for creating high-performance and scalable data-driven enterprise Web and deskto...

Related podcasts

Events coming up

  • Mar 15

    DevWeek 2010

    London, United Kingdom

    DevWeek is Europe’s leading independent conference for software developers, database professionals and IT architects, and features expert speakers on a wide range of topics, including .NET 4.0, Silverlight 3, WCF 4, Visual Studio 2010, REST, Windows Workflow 4, Thread Synchronization, ASP.NET 4.0, SQL Server 2008 R2, LINQ, Unit Testing, CLR & C# 4.0, .NET Patterns, WPF 4, F#, Windows Azure, ADO.NET, Entity Framework, Debugging, T-SQL Tips & Tricks, and more.

We'd love to hear what you think! Submit ideas or give us feedback