Click here to Skip to main content
15,893,588 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I´m trying to create a custom GridView with additional functionality but I do have problem with PostBack which are "simulated" by "Button2". On every PostBack (after a first DataBinding) the content of one DataRow gets erased until the GridView is fully empty. It has something to do with AddCustomControls() within the PreRender event. But I don´t know how to fix this issue. Does anybody have an idea? Any help would be greatly appreciated.

Maybe the following picture describes the behavior better than my words:

http://i.stack.imgur.com/r1W7T.png[^]

With DataBind() in the OnLoad event and AddCustomControls in the OnDataBound event it worked pretty well. The table stayed exactly the same between PostBacks. But I couldn´t use this "solution" (which is also not very elegant) anymore when I tried to implement the editing of the grid. Logically the edited values within the TextBoxes were overriden by the DataBind() in OnLoad.

Somehow it has to do with "headerTable.Rows.AddAt(1, controlRow);". If I do "headerTable.Rows.Add(controlRow);" which adds the row at the end everything works finde. So the content AFTER this kind of header row get cleared...

XML
Web.config
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
      <pages>
        <controls>
          <add tagPrefix="asp" assembly="WebApplication11" namespace="WebApplication11"/>
        </controls>
      </pages>
    </system.web>
</configuration>


XML
Default.aspx
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:mightygridview
            ID="mightyGridView"
            runat="server"
            AllowSorting="true"
            AllowHiding="true"
            AutoGenerateEditButton="false"
            OnRowUpdating="mightyGridView_RowUpdating">
        </asp:mightygridview>

        <br />

        <asp:Button ID="Button1" runat="server" Text="Button - Binding" onclick="Button1_Click" />
        <asp:Button ID="Button2" runat="server" Text="Button - Nothing" />
    </div>
    </form>
</body>
</html>


C#
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
    DataTable tbl = new DataTable();
    DataRow row;

    tbl.Columns.Add("Spalte A");
    tbl.Columns.Add("Spalte B");
    tbl.Columns.Add("Spalte C");

    row = tbl.NewRow();
    row[0] = "Spalte A, Zeile 1";
    row[1] = "Spalte B, Zeile 1";
    row[2] = "Spalte C, Zeile 1";
    tbl.Rows.Add(row);

    row = tbl.NewRow();
    row[0] = "Spalte A, Zeile 2";
    row[1] = "Spalte B, Zeile 2";
    row[2] = "Spalte C, Zeile 2";
    tbl.Rows.Add(row);

    row = tbl.NewRow();
    row[0] = "Spalte A, Zeile 3";
    row[1] = "Spalte B, Zeile 3";
    row[2] = "Spalte C, Zeile 3";
    tbl.Rows.Add(row);

    mightyGridView.DataSource = tbl;
    mightyGridView.DataBind();
}


C#
public class MightyGridView : GridView
{
    public MightyGridView()
    {
        _images = new Dictionary<_imageTypes, string>();
        _images.Add(_imageTypes.SortAsc, "data:;base64,...");
        _images.Add(_imageTypes.SortAscActive, "data:;base64,...");
        _images.Add(_imageTypes.SortDesc, "data:;base64,...");
        _images.Add(_imageTypes.SortDescActive, "data:;base64,...");
        _images.Add(_imageTypes.HideColumn, "data:;base64,...");
        _images.Add(_imageTypes.ShowAllColumns, "data:;base64,...");
    }

    private enum _imageTypes { SortAsc, SortAscActive, SortDesc, SortDescActive, HideColumn, ShowAllColumns }
    private readonly Dictionary<_imageTypes, string> _images;

    public new bool AllowSorting { get; set; }
    public bool AllowHiding { get; set; }
    public override object DataSource
    {
        get
        {
            return Page.Session[this.ID + ".DataSource"];
        }

        set
        {
            Page.Session[this.ID + ".DataSource"] = value;
            base.DataSource = value;
        }
    }

    private void AddCustomControlsRow()
    {
        if (DataSource != null)
        {
            if (AllowSorting || AllowHiding)
            {
                DataTable dataTable = GetDataTableFromDataSource();

                if (dataTable.Columns.Count > 0 && dataTable.Rows.Count > 0)
                {
                    if (this.HeaderRow != null && this.HeaderRow.Parent != null)
                    {
                        string sortExpression = dataTable.DefaultView.Sort.Replace(" ASC", "").Replace(" DESC", "");
                        SortDirection sortDirection = dataTable.DefaultView.Sort.EndsWith(" ASC") ? SortDirection.Ascending : SortDirection.Descending;

                        Table headerTable = (Table)this.HeaderRow.Parent;
                        GridViewRow controlRow = new GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
                        TableCell controlCell;
                        ImageButton imageButton;

                        foreach (TableCell cell in this.HeaderRow.Cells)
                        {
                            // Sicherstellen, dass es nicht die Spalte mit den Bearbeiten-Buttons ist, welche keine Überschrift enthält.
                            if (!(cell.Text.Replace(" ", "").Trim().Length > 0))
                            {
                                controlCell = new TableCell();

                                cell.Attributes.Add("style", "border-bottom: 0");
                                controlCell.Attributes.Add("style", "border-top: 0; text-align: center");

                                controlRow.Cells.Add(controlCell);
                            }

                            else
                            {
                                controlCell = new TableCell();

                                cell.Attributes.Add("style", "border-bottom: 0");
                                controlCell.Attributes.Add("style", "border-top: 0; text-align: center");

                                if (AllowSorting)
                                {
                                    imageButton = new ImageButton();
                                    imageButton.Attributes.Add("data-column-name", cell.Text);
                                    imageButton.Click += new ImageClickEventHandler(SortColumnAscButton_Click);

                                    if (sortExpression == cell.Text && sortDirection == SortDirection.Ascending)
                                        imageButton.ImageUrl = _images[_imageTypes.SortAscActive];
                                    else
                                        imageButton.ImageUrl = _images[_imageTypes.SortAsc];

                                    controlCell.Controls.Add(imageButton);

                                    imageButton = new ImageButton();
                                    imageButton.Attributes.Add("data-column-name", cell.Text);
                                    imageButton.Click += new ImageClickEventHandler(SortColumnDescButton_Click);

                                    if (sortExpression == cell.Text && sortDirection == SortDirection.Descending)
                                        imageButton.ImageUrl = _images[_imageTypes.SortDescActive];
                                    else
                                        imageButton.ImageUrl = _images[_imageTypes.SortDesc];

                                    controlCell.Controls.Add(imageButton);

                                    controlRow.Cells.Add(controlCell);
                                }

                                if (AllowHiding)
                                {
                                    imageButton = new ImageButton();
                                    imageButton.Attributes.Add("data-column-name", cell.Text);
                                    imageButton.Click += new ImageClickEventHandler(HideColumnButton_Click);
                                    imageButton.ImageUrl = _images[_imageTypes.HideColumn];
                                    controlCell.Controls.Add(imageButton);

                                    controlRow.Cells.Add(controlCell);
                                }
                            }
                        }

                        headerTable.Rows.AddAt(1, controlRow);
                    }
                }
            }
        }
    }

    public static DataTable GetDataTableFromIEnumerable(IEnumerable enumerable)
    {
        DataTable dataTable = new DataTable();
        DataRow row;
        PropertyInfo[] propertyInfos;

        foreach (object obj in enumerable)
        {
            propertyInfos = obj.GetType().GetProperties();

            if (dataTable.Columns.Count == 0)
                foreach (PropertyInfo pi in propertyInfos)
                    dataTable.Columns.Add(pi.Name, pi.PropertyType);

            row = dataTable.NewRow();

            foreach (PropertyInfo pi in propertyInfos)
            {
                object value = pi.GetValue(obj, null);
                row[pi.Name] = value;
            }

            dataTable.Rows.Add(row);
        }

        return dataTable;
    }

    private DataTable GetDataTableFromDataSource()
    {
        DataTable dataTable;

        if (DataSource is DataTable)
            dataTable = (DataTable)DataSource;

        else if (DataSource is IEnumerable)
            dataTable = GetDataTableFromIEnumerable((IEnumerable)DataSource);

        else
            throw new NotSupportedException("Typ wird nicht unterstützt.");

        return dataTable;
    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
    }

    protected override void OnLoad(EventArgs e)
    {
        // Weg der funktionierte, jedoch mit Editing Probleme macht: OnLoad: DataBind() / OnDataBound: AddCustomControls.
        // Das DataBinding überschrieb die geänderten Werte wieder.

        base.OnLoad(e);
    }

    protected override void OnDataBinding(EventArgs e)
    {
        base.OnDataBinding(e);
    }

    protected override void OnDataBound(EventArgs e)
    {
        base.OnDataBound(e);
    }

    protected override void OnPreRender(EventArgs e)
    {
        AddCustomControlsRow();

        base.OnPreRender(e);
    }

    protected override void OnUnload(EventArgs e)
    {
        base.OnUnload(e);
    }

    protected void SortColumnAscButton_Click(object sender, ImageClickEventArgs e)
    {
        DataTable dataTable = GetDataTableFromDataSource();
        dataTable.DefaultView.Sort = ((ImageButton)sender).Attributes["data-column-name"] + " ASC";

        DataSource = dataTable;
        DataBind();
    }

    protected void SortColumnDescButton_Click(object sender, ImageClickEventArgs e)
    {
        DataTable dataTable = GetDataTableFromDataSource();
        dataTable.DefaultView.Sort = ((ImageButton)sender).Attributes["data-column-name"] + " DESC";

        DataSource = dataTable;
        DataBind();
    }

    protected void HideColumnButton_Click(object sender, ImageClickEventArgs e)
    {
        // todo: Improve. Backup zum resetten, etc.
        DataTable dataTable = GetDataTableFromDataSource();
        dataTable.Columns.Remove(((ImageButton)sender).Attributes["data-column-name"]);

        DataSource = dataTable;
        DataBind();
    }
Posted
Updated 20-Jun-12 2:54am
v5
Comments
Sandeep Mewara 20-Jun-12 7:45am    
When you are posting a question here, you should have time and make effort posting it fully over here. Referencing the question on other site is not suggestible.
timmkrause 20-Jun-12 8:10am    
Okay, sorry. I took me the time now.
Sandeep Mewara 20-Jun-12 7:47am    
BTW, I went through the question on SO, but could not find any question. You just shared your code and said 'strange behavior'.
timmkrause 20-Jun-12 8:10am    
I tried to keep things simple and refer people to my image. I thought this would have described it better than any of my words.
Mohamed Mitwalli 20-Jun-12 8:01am    
what is the problem ???

1 solution

Moved it to OnRowCreated which is also fired on every PostBack of the life cycle:

C#
protected override void OnRowCreated(GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.Header)
    {
        if (AllowSorting || AllowHiding)
            AddHeaderControls(e.Row);
    }

    base.OnRowCreated(e);
}


It also fixed the behavior of the sort buttons etc. A click on a (sort) button did not trigger the event because the "binding" in the PreRender is too late to handle the event.
I also changed the AddHeaderControls method a bit, instead of adding a whole row, I add the controls to the cell itself, here is a snippet:

C#
foreach (TableCell cell in row.Cells)
                {
                    // Sicherstellen, dass es nicht die Spalte mit den Bearbeiten-Buttons ist, welche keine Überschrift enthält.
                    if (cell.Text.Replace("&nbsp;", string.Empty).Trim().Length > 0)
                    {
                        // Write the Header Text into the cell as a (Literal)Control, because it would be lost otherwise.
                        cell.Controls.Add(new LiteralControl(cell.Text));
                        cell.Controls.Add(new LiteralControl("<br />"));

                        if (AllowSorting)
                        {
                            imageButton = new ImageButton();
                            imageButton.Attributes.Add("data-column-name", cell.Text);
                            imageButton.Click += new ImageClickEventHandler(SortColumnAscButton_Click);
                            if (sortExpression == cell.Text && sortDirection == SortDirection.Ascending)
                                imageButton.ImageUrl = _images[_imageTypes.SortAscActive];
                            else
                                imageButton.ImageUrl = _images[_imageTypes.SortAsc];
                            cell.Controls.Add(imageButton);

                            imageButton = new ImageButton();
                            imageButton.Attributes.Add("data-column-name", cell.Text);
                            imageButton.Click += new ImageClickEventHandler(SortColumnDescButton_Click);
                            if (sortExpression == cell.Text && sortDirection == SortDirection.Descending)
                                imageButton.ImageUrl = _images[_imageTypes.SortDescActive];
                            else
                                imageButton.ImageUrl = _images[_imageTypes.SortDesc];
                            cell.Controls.Add(imageButton);
                        }

                        if (AllowHiding)
                        {
                            imageButton = new ImageButton();
                            imageButton.Attributes.Add("data-column-name", cell.Text);
                            imageButton.Click += new ImageClickEventHandler(HideColumnButton_Click);
                            imageButton.ImageUrl = _images[_imageTypes.HideColumn];
                            cell.Controls.Add(imageButton);
                        }
                    }
                }
 
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