views:

632

answers:

3

Hi,

I have a simple ASP page with databound grid (bound to an object source). The grid is within the page of a wizard and has a 'select' checkbox for each row.

In one stage of the wizard, I bind the GridView:

protected void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
    {
...
        // Bind and display matches
        GridViewMatches.EnableViewState = true;
        GridViewMatches.DataSource = getEmailRecipients();
        GridViewMatches.DataBind();

And when the finish button is clicked, I iterate through the rows and check what's selected:

protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
    // Set the selected values, depending on the checkboxes on the grid.
    foreach (GridViewRow gr in GridViewMatches.Rows)
    {
        Int32 personID = Convert.ToInt32(gr.Cells[0].Text);
        CheckBox selected = (CheckBox) gr.Cells[1].FindControl("CheckBoxSelectedToSend");

But at this stage GridViewMatches.Rows.Count = 0! I don't re-bind the grid, I shouldn't need to, right? I expect the view-state to maintain the state. (Also, if I do rebind the grid, my selection checkboxes will be cleared)

NB: This page also dynamically adds user controls in OnInit method. I have heard that it might mess with the view state, but as far as I can tell, I am doing it correctly and the viewstate for those added controls seems to work (values are persisted between postbacks)

Thanks a lot in advance for any help!

Ryan

UPDATE: Could this be to do with the fact I am setting the datasource programatically? I wondered if the asp engine was databinding the grid during the page lifecycle to a datasource that was not yet defined. (In a test page, the GridView is 'automatically' databound'. I don't want the grid to re-bound I just want the values from the viewstate from the previous post!

Also, I have this in the asp header: ViewStateEncryptionMode="Never" - this was to resolve an occasional 'Invalid Viewstate Validation MAC' message

For reference, my GridView is defined as follows:

<asp:GridView ID="GridViewMatches" runat="server" AllowSorting="True" AutoGenerateColumns="False" 
    BackColor="White" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="3" 
    OnDataBinding="GridViewMatches_OnBinding">
        <Columns>
            <asp:BoundField DataField="PersonID"><ItemStyle CssClass="hidden"/></asp:BoundField>
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:CheckBox ID="CheckBoxSelectedToSend" runat="server"
                        Checked='<%# DataBinder.Eval(Container.DataItem, "SelectedToSend") %>'/>
                </ItemTemplate>
...

Thanks again

Ryan

A: 

Make sure your GridView ViewState is on by default.

Verify that the GridView is not being rebound or cleared.

If it still doesn't work, then check any of the parent controls of your GridView and make sure their ViewState is NOT turned off. Any parent controls with ViewState turned off will cause all their child controls to not use ViewState.

The dynamic controls shouldn't have any impact on your GridView unless your GridView is contained within one of these dynamic controls.

Kelsey
Hi, thanks a lot for your response. I changed the GridView def to enable Viewstate: EnableViewState="True" and checked that I bind the grid in one place only (the 'next' event of the wizard). It's still not working! Viewstate is fine for other controls on the same page (in other steps of the wizard). This is driving me nuts!
Ryan
+1  A: 

Do your gridview and other controls have an ID? If you don't specify an ID, or if the ID changes between postbacks, you will lose viewstate changes.

SLC
Great thought! But alas, it has an ID. I have added the definition of my GridView to the question
Ryan
A: 

Iterating the controls in the PreInit event (to detect if the 'add another control' or 'remove another control' button was pressed) invalidates the view state!!

Here is the method called from PreInit

public Control GetPostBackControl(Page thePage)
    {
        //return null;

        Control myControl = null;
        string ctrlName = thePage.Request.Params.Get("__EVENTTARGET");
        if (((ctrlName != null) & (ctrlName != string.Empty)))
        {
            myControl = thePage.Master.FindControl(ctrlName);
        }
        else
        {
            foreach (string Item in thePage.Request.Form)
            {
                Control c = thePage.Master.FindControl(Item);
                if (((c) is System.Web.UI.WebControls.Button))
                {
                    myControl = c;
                }
            }

        }

        return myControl;
    }

(I take no credit for this methd, I found it on the web)

If the first line is uncommented, the viewstate is maintained.

Awful!

Ryan