ASPxGridView allow sorting and DataItemTemplate with ASPxCheckBox

1.7k views Asked by At

I have an ASPxGridView that contains a column with a DataItemTemplate that contains an ASPxCheckBox. I then have a button outside of the grid that performs some actions based on whether the checkbox is checked.

The grid is defined as:

<dx:ASPxGridView ID="grid" runat="server">
    <Columns>
        <dx:GridViewDataColumn>
            <DataItemTemplate>
                <ds:ASPxCheckBox ID="checkbox" runat="server" />
            </DataItemTemplate>
        </dx:GridViewDataColumn>
    <Columns>
</dx:ASPxGridView>

The grid is populated in Page_Load as such:

protected void Page_Load(object sender, EventArgs e)
{
    //Some stuff
    grid.DataSource = sourceTable;
    grid.DataBind();
    //Other stuff
}

Where sourceTable is defined as:

public DataTable sourceTable
{
    get
    {
        if (ViewState["sourceTable"] == null)
            return new DataTable();
        return (DataTable)ViewState["sourceTable"];
    }
    set
    {
        ViewState["sourceTable"] = value;
    }
}

And populated elsewhere. (The population is not important and works)

The code is implemented as such to ensure that sorting and paging works correctly on the grid, as defined in various DevExpress support topics. This is understandable. However, when we try to get the Checked value from checkbox on the button click, it is always false:

protected void button_Click(object sender, EventArgs e)
{
    //Some stuff
    for(int i = 0; i < grid.VisibleRowCount; i++)
    {
        //Other stuff
        ASPxCheckBox checkbox = grid.FindRowCellTemplateControl(i, grid.Columns[0], "checkbox") as ASPxCheckBox;
        if(checkbox.Checked) //Always false
        {
            //Do conditional stuff
        }
        //More stuff
    }
    //Even more stuff
}

I understand why this is always false as the grid rebinds the data and recreates the checkbox to its default state, any documentation I have found for this issue regarding DevExpress states to wrap the data binding in Page_Load in if(!Page.IsPostBack) which does indeed work, but breaks sorting and paging.

I'm sure I have the solution for this in other projects I have done, I just can't find it. What should be done in this case?

Note: I have shortened the code to as little as I can possibly get away with and have not tested it. There may be some small errors with the actual code, but use it as a guide to what I am trying to do and will clarify any issues people may come across.

EDIT: Using if(!Page.IsPostBack) or if(!Page.IsCallback) in Page_Load stops sorting and paging on the grid, removing this condition means Checked is always false. I need both sorting/paging to occur AND to be able to read the Checked value of the ASPxCheckBox in the DataItemTemplate.

3

There are 3 answers

8
Jaqen H'ghar On BEST ANSWER

Edited answer

It appears that when using editors in DataItemTemplate you have to use LoadPostData() to get their values.

Use:

for(int i = 0; i < grid.VisibleRowCount; i++)
{
    ASPxCheckBox checkbox = grid.FindRowCellTemplateControl(i, grid.Columns[0], "checkbox") as ASPxCheckBox;

    ((IPostBackDataHandler)checkbox).LoadPostData(checkbox.UniqueID, Request.Form);

    if(checkbox.Checked)
    {
        //Do conditional stuff
    }
}

As for populating the grid, you can keep it inside the Page_Load without !IsPostBack because it does not affect the editors (and it will keep the filtering/sorting)

It can cause problems in other cases but this is not the case here.

Hope it helps! Please tell me if you have any questions

4
Valeh Mikayilzadeh On

Because when you button click then page post to server and when page posting to server all control set to default value (If you don`t control isPostBack property). you grid control sorting doing in client side. but posting to server side and rendering to client side you sorting removed. You can use Callback. Ex:

  <dx:ASPxGridView ID="grid" runat="server" ClientInstanceName="grid" OnCustomCallback="ASPxGridView1_CustomCallback">
            <Columns>
                <dx:GridViewDataColumn>
                    <DataItemTemplate>
                        <dx:ASPxCheckBox ID="checkbox" runat="server" />
                    </DataItemTemplate>
                </dx:GridViewDataColumn>
            </Columns>
   </dx:ASPxGridView>


 <dx:ASPxButton ID="btnSend" runat="server" AutoPostBack="False" Text="Send" Width="100px" ClientInstanceName="btnSend">
<ClientSideEvents Click="function(s, e) { grid.PerformCallback(); }" />
</dx:ASPxButton>

Code behind:

if (!IsPostBack)
        {
            //Some stuff

            grid.DataSource = sourceTable;

            grid.DataBind();

            //Other stuff
        }

protected void ASPxGridView1_CustomCallback(object sender, DevExpress.Web.ASPxGridViewCustomCallbackEventArgs e)
    {
        for (int i = 0; i < grid.VisibleRowCount; i++)
        {
            //Other stuff

            ASPxCheckBox checkbox = grid.FindRowCellTemplateControl(i, grid.DataColumns[0], "checkbox") as ASPxCheckBox;

            if (checkbox.Checked) //Always false

            {

                //Do conditional stuff

            }

            //More stuff

        }
    }

show difference between callback and postback in c# Difference between a Postback and a Callback

3
nempoBu4 On

There are some variants.

Page_Init event handler

You can try to move your binding code to Page_Init event handler.

protected void Page_Init(object sender, EventArgs e)
{
    grid.DataSource = sourceTable;
    grid.DataBind();
}

PostData of CheckBox editor is loaded between Page_Init and Page_Load, so the values in your CheckBox column are going to be erased in Page_Load event after calling to grid.DataBind method.


GridViewCommandColumn with ShowSelectCheckbox="true"

Here is another possibility. You can imitate the desired behavior by using GridViewCommandColumn with ShowSelectCheckbox property.

<dx:GridViewCommandColumn ShowSelectCheckbox="true" />

You can use grid.Selection.IsRowSelected method to get the checked rows .
Here is example:

protected void Button1_Click(object sender, EventArgs e)
{
    //Some stuff
    for (int i = 0; i < grid.VisibleRowCount; i++)
    {
        //Other stuff                
        if (grid.Selection.IsRowSelected(i))
        {
            //Do conditional stuff
        }
        //More stuff
    }
    //Even more stuff
}