Click here to Skip to main content
15,919,749 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
i need to one help in solving one issue in my academic project a help will be appreciated. I struck in the one area not able to solve.

I have seperated the concern in POC program, Description of the problem is as follows:

Im building the datatable at runtime i.e dynamic columns without rows then binding columns from the datatable to gridview through templatefields as i need different controls.since i need a feature in the gridview that whenever new row is added it should be edit mode i used customized grideview which does this. now the problem after bindng the column if i add or modify the contain the gridview textchange event is not occuring hence dirtyrow collection is empty. Can you help me in solving this i have added below the code for custom gridview and my aspx.cs file.please help me.

POCGrideview.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class POCGridView : System.Web.UI.Page
{
DataTable dt = new DataTable();

/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{

    if (!IsPostBack)
    {
        //build the datatable
        dt = BuildDataTable();
        //adding data to table
        InsertTableData(dt, 1, "Sameer");
        InsertTableData(dt, 2, "Ahmed");
        Session["Table"] = dt;

        BindTableToGrid();
    }
}

/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void CreateButton_Click(object sender, EventArgs e)
{
    //bind the template field
    BindTableToGrid();

}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void AddRowButton_Click(object sender, EventArgs e)
{
    //Add the data to Grid
    AddRow();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void SaveDataButton_Click(object sender, EventArgs e)
{
    //Save the data
    SaveData();
}

/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void DeleteRowButton_Click(object sender, EventArgs e)
{
    //DeleteDataTableRows
    DeleteData();

}

#region helper functions
/// <summary>
///
/// </summary>
/// <param name="dt"></param>
/// <param name="RowId"></param>
/// <param name="strData"></param>
private void InsertTableData(DataTable dt, int RowId, String strData)
{
    DataRow dr = dt.NewRow();
    dr["RowId"] = RowId;
    dr["Data"] = strData;
    dt.Rows.Add(dr);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private DataTable BuildDataTable()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("RowId", Type.GetType("System.Int32"));
    dt.Columns.Add("Data", Type.GetType("System.String"));
    return dt;
}

/// <summary>
///
/// </summary>
private void AddTemplateFieldsToGrid()
{
    if (Session["Table"] != null)
    {
        DataTable dt = Session["Table"] as DataTable;
        foreach (DataColumn col in dt.Columns)
        {
            TemplateField tmpField = new TemplateField();
            tmpField.HeaderTemplate = new MyTemplateClass(ListItemType.Header, col.ColumnName);
            tmpField.EditItemTemplate = new MyTemplateClass(ListItemType.EditItem, col.ColumnName);
            BulkEditGridView1.Columns.Add(tmpField);
        }
    }
}

/// <summary>
///
/// </summary>
private void BindTableToGrid()
{
    if (Session["Table"] != null)
    {
        DataTable dt = Session["Table"] as DataTable;
        AddTemplateFieldsToGrid();
        BulkEditGridView1.DataSource = dt;
        BulkEditGridView1.DataBind();

    }
}
/// <summary>
///
/// </summary>
private void AddRow()
{
    if (Session["Table"] != null)
    {
        DataTable dt = Session["Table"] as DataTable;
        DataRow dr = dt.NewRow();
        dt.Rows.Add(dr);
        Session["Table"] = dt;
    }
    BindTableToGrid();

}
/// <summary>
///
/// </summary>
private void SaveData()
{
    if (Session["Table"] != null)
    {
        DataTable dt = Session["Table"] as DataTable;
        dt.WriteXml("Data.xml");
    }
}
/// <summary>
///
/// </summary>
private void DeleteData()
{
    if (Session["Table"] != null)
    {
        DataTable dt = Session["Table"] as DataTable;
        dt.Rows.Clear();
        Session["Table"] = dt;
    }
}
#endregion

protected class MyTemplateClass : ITemplate
{
    private string ColumnName;
    private ListItemType Item;

    public MyTemplateClass(ListItemType item, string columnName)
    {
        Item = item;
        ColumnName = columnName;
    }


    #region ITemplate Members

    public void InstantiateIn(Control container)
    {
        switch (Item)
        {
            case ListItemType.Header:
                Label lbl = new Label();
                lbl.Text = ColumnName;
                container.Controls.Add(lbl);
                break;
            case ListItemType.EditItem:
                TextBox txt = new TextBox();
                txt.DataBinding += new EventHandler(txt_DataBinding);
                txt.TextChanged += new EventHandler(txt_TextChanged);
                txt.AutoPostBack = true;
                txt.Columns = 3;
                container.Controls.Add(txt);
                break;
            case ListItemType.Footer:
                break;
        }
    }

    void txt_TextChanged(object sender, EventArgs e)
    {
        int i = 0;
    }

    void txt_DataBinding(object sender, EventArgs e)
    {
        TextBox txt = (TextBox)sender;
        GridViewRow gridrow = (GridViewRow)txt.NamingContainer;
        object value = DataBinder.Eval(gridrow.DataItem, ColumnName);
        if (value != null)
        {
            txt.Text = Convert.ToString(value);
        }
    }

    #endregion
}
protected void BulkEditGridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    Response.Write("test");

}
protected void BulkEditGridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
    Response.Write("GridView");
}
}


BulkEditGridView1.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Collections;
using System.Collections.Specialized;
using System.Web;

namespace RealWorld.Grids
{
/// <summary>
/// BulkEditGridView allows users to edit multiple rows of a gridview at once, and have them
/// all saved.
/// </summary>
[
DefaultEvent("SelectedIndexChanged"),
Designer("System.Web.UI.Design.WebControls.GridViewDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
ControlValueProperty("SelectedValue"),
]
public class BulkEditGridView : System.Web.UI.WebControls.GridView
{
    //key for the RowInserting event handler list
    public static readonly object RowInsertingEvent = new object();

    private List<int> dirtyRows = new List<int>();
    private List<int> newRows = new List<int>();

    /// <summary>
    /// Default Constructor
    /// </summary>
    public BulkEditGridView()
    {
    }

    /// <summary>
    /// Modifies the creation of the row to set all rows as editable.
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <param name="dataSourceIndex"></param>
    /// <param name="rowType"></param>
    /// <param name="rowState"></param>
    /// <returns></returns>
    protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
    {
        return base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState | DataControlRowState.Edit);
    }

    public List<GridViewRow> DirtyRows
    {
        get
        {
            List<GridViewRow> drs = new List<GridViewRow>();
            foreach (int rowIndex in dirtyRows)
            {
                drs.Add(this.Rows[rowIndex]);
            }

            return drs;
        }
    }

    /// <summary>
    /// Adds event handlers to controls in all the editable cells.
    /// </summary>
    /// <param name="row"></param>
    /// <param name="fields"></param>
    protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
    {
        base.InitializeRow(row, fields);
        foreach (TableCell cell in row.Cells)
        {
            if (cell.Controls.Count > 0)
            {
                AddChangedHandlers(cell.Controls);
            }
        }
    }

    /// <summary>
    /// Adds an event handler to editable controls.
    /// </summary>
    /// <param name="controls"></param>
    private void AddChangedHandlers(ControlCollection controls)
    {
        foreach (Control ctrl in controls)
        {
            if (ctrl is TextBox)
            {
                ((TextBox)ctrl).TextChanged += new EventHandler(this.HandleRowChanged);
            }
            else if (ctrl is CheckBox)
            {
                ((CheckBox)ctrl).CheckedChanged += new EventHandler(this.HandleRowChanged);
            }
            else if (ctrl is DropDownList)
            {
                ((DropDownList)ctrl).SelectedIndexChanged += new EventHandler(this.HandleRowChanged);
            }
            ////could add recursion if we are missing some controls.
            //else if (ctrl.Controls.Count > 0 && !(ctrl is INamingContainer) )
            //{
            //    AddChangedHandlers(ctrl.Controls);
            //}
        }
    }


    /// <summary>
    /// This gets called when a row is changed.  Store the id of the row and wait to update
    /// until save is called.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    void HandleRowChanged(object sender, EventArgs args)
    {
        GridViewRow row = ((Control)sender).NamingContainer as GridViewRow;
        if (null != row)
        {
            if (0 != (row.RowState & DataControlRowState.Insert))
            {
                int altRowIndex = this.InnerTable.Rows.GetRowIndex(row);
                if (false == newRows.Contains(altRowIndex))
                    newRows.Add(altRowIndex);
            }
            else
            {
                if (false == dirtyRows.Contains(row.RowIndex))
                    dirtyRows.Add(row.RowIndex);
            }
        }

    }

    /// <summary>
    /// Setting this property will cause the grid to update all modified records when
    /// this button is clicked.  It currently supports Button, ImageButton, and LinkButton.
    /// If you set this property, you do not need to call save programatically.
    /// </summary>
    [IDReferenceProperty(typeof(Control))]
    public string SaveButtonID
    {
        get
        {
            return (string)(this.ViewState["SaveButtonID"] ?? String.Empty);
        }
        set
        {
            this.ViewState["SaveButtonID"] = value;
        }
    }

    /// <summary>
    /// Attaches an eventhandler to the onclick method of the save button.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        //Attach an event handler to the save button.
        if (false == string.IsNullOrEmpty(this.SaveButtonID))
        {
            Control btn = RecursiveFindControl(this.NamingContainer, this.SaveButtonID);
            if (null != btn)
            {
                if (btn is Button)
                {
                    ((Button)btn).Click += new EventHandler(SaveClicked);
                }
                else if (btn is LinkButton)
                {
                    ((LinkButton)btn).Click += new EventHandler(SaveClicked);
                }
                else if (btn is ImageButton)
                {
                    ((ImageButton)btn).Click += new ImageClickEventHandler(SaveClicked);
                }
            }
        }
    }

    /// <summary>
    /// Looks for a control recursively up the control tree.  We need this because Page.FindControl
    /// does not find the control if we are inside a masterpage content section.
    /// </summary>
    /// <param name="namingcontainer"></param>
    /// <param name="controlName"></param>
    /// <returns></returns>
    private Control RecursiveFindControl(Control namingcontainer, string controlName)
    {
        Control c = namingcontainer.FindControl(controlName);

        if (c != null)
            return c;

        if (namingcontainer.NamingContainer != null)
            return RecursiveFindControl(namingcontainer.NamingContainer, controlName);

        return null;
    }

    /// <summary>
    /// Handles the save event, and calls the save method.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void SaveClicked(object sender, EventArgs e)
    {
        this.Save();
        this.DataBind();
    }

    /// <summary>
    /// Saves any modified rows.  This is called automatically if the SaveButtonId is set.
    /// </summary>
    public void Save()
    {
        try
        {
            foreach (int row in dirtyRows)
            {
                //TODO: need to check if we really want false here.  Probably want to pull this
                //fron the save button.
                this.UpdateRow(row, false);
            }

            foreach (int row in newRows)
            {
                //Make the datasource save a new row.
                this.InsertRow(row, false);
            }
        }
        finally
        {
            dirtyRows.Clear();
            newRows.Clear();
        }
    }

    /// <summary>
    /// Prepares the <see cref="RowInserting"/> event and calls insert on the DataSource.
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <param name="causesValidation"></param>
    private void InsertRow(int rowIndex, bool causesValidation)
    {
        GridViewRow row = null;

        if ((!causesValidation || (this.Page == null)) || this.Page.IsValid)
        {
            DataSourceView dsv = null;
            bool useDataSource = base.IsBoundUsingDataSourceID;
            if (useDataSource)
            {
                dsv = this.GetData();
                if (dsv == null)
                {
                    throw new HttpException("DataSource Returned Null View");
                }
            }
            GridViewInsertEventArgs args = new GridViewInsertEventArgs(rowIndex);
            if (useDataSource)
            {
                if ((row == null) &&
Posted
Updated 3-Aug-10 10:12am
v2
Comments
Sandeep Mewara 3-Aug-10 15:12pm    
Reason for my vote of 1
Code dump... that too without PRE tags.
OriginalGriff 3-Aug-10 16:13pm    
Code block added to preserve formatting. It's now a bit more readable. Still not going to read that much, and you forgot the end, but hey! Sandeep should be happier!
OriginalGriff 3-Aug-10 16:14pm    
Reason for my vote of 1
Even with the code blocks added, it's still way too much to read. Cut it down to the relevant bits, doood!

1 solution

You are creating everything dynamically, even the template columns like using AddTemplateFieldsToGrid();
Now, if you see you have used this above method to add templates in BindTableToGrid() method which is called for first time when page loads but not during postbacks.
Since, it was dynamically created, on consecutive postbacks you need to re-create them in order to raise the events. If you don't they get lost.
This happens as the control that was created for first time during page load no more exists during post back.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900