3

Background

I have a GridView that builds a table using an ObjectDataSource. This source uses web services for both the select and update segments. Under the edit section, when clicked, has a DropDownList appear for the two columns that need to be editable. The DropDownLists both use separate ObjectDataSources storing WebServices that obtain the values meant to be stored in this DropDownList.

Currently working

At the moment, all of the above works. When I load the page, the table comes up with the proper data. When I click on the edit button, the two DropDownLists come up with the proper data stored in them from the WebService.

The Problem

When I select an option to update the DB or when I select cancel, the page throws an error and fails. I am not entirely sure why this happens, other than that it has to do with the binding not being handled correctly. I would like to know how to bind the values obtained from the DropDownList to be used when updating the database?

Below you will find what i have tried so far:

<asp:GridView ID="GridViewHolder" 
                          runat="server" 
                          AllowPaging="True" 
                          AutoGenerateColumns="False" 
                          BackColor="Transparent" 
                          BorderColor="#999999" 
                          BorderStyle="Ridge" 
                          BorderWidth="3px" 
                          CellPadding="4" 
                          CellSpacing="2" 
                          DataSourceID="MachineDataSet" 
                          ForeColor="Black" 
                          HeaderStyle-HorizontalAlign="Center" 
                          HorizontalAlign="Center"  
                          RowStyle-HorizontalAlign="Center" Width="574px"
                          OnRowUpdating="GridViewHolder_Updating"
                          OnRowCancelingEdit="GridViewHolder_Canceling"
                          OnRowUpdated="GridViewHolder_Updated"
                          OnRowEditing="GridViewHolder_Editing">
                <RowStyle BackColor="Transparent" HorizontalAlign="Center" />
                <Columns>
                    <asp:BoundField DataField="ID" 
                                    HeaderText="ID" 
                                    SortExpression="ID" 
                                    Visible="False" />
                    <asp:BoundField DataField="SiteName" 
                                    HeaderText="Site Name" 
                                    SortExpression="SiteName"
                                    ReadOnly="true" />
                    <asp:BoundField DataField="Name" 
                                    HeaderText="Machine Name" 
                                    ReadOnly="true" 
                                    SortExpression="Name" />
                    <asp:TemplateField HeaderText="Machine Type" SortExpression="MachineType">
                        <EditItemTemplate>
                            <asp:ObjectDataSource ID="GetMachineType" 
                                                  runat="server" 
                                                  SelectMethod="GetMachineTypeList" 
                                                  TypeName="Datamart.UI.Reporting.Web.FilteredReportInputsSvc.FilteredReportInputsService">
                                <SelectParameters>
                                    <asp:Parameter Name="siteid" Type="String" />
                                </SelectParameters>
                            </asp:ObjectDataSource>
                            <asp:DropDownList ID="MachineTypeDropDown" 
                                              runat="server" 
                                              AppendDataBoundItems="True" 
                                              DataSourceID="GetMachineType" 
                                              DataTextField="Name" 
                                              DataValueField="ID"                                               
                                              Height="21px" 
                                              Width="217px">
                                <asp:ListItem Enabled="true" 
                                              Text="Select a Machine Type.">
                                </asp:ListItem>
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label1" 
                                       runat="server" 
                                       Text='<%# Bind("MachineType") %>'>
                            </asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Machine Model" SortExpression="MachineModel">
                        <EditItemTemplate>
                            <asp:ObjectDataSource ID="GetMachineModel" 
                                                  runat="server" 
                                                  SelectMethod="GetMachineModelList" 
                                                  TypeName="Datamart.UI.Reporting.Web.FilteredReportInputsSvc.FilteredReportInputsService">
                                <SelectParameters>
                                    <asp:Parameter Name="siteid" Type="String" />
                                </SelectParameters>
                            </asp:ObjectDataSource>
                            <asp:DropDownList ID="MachineModelDropDown" 
                                              runat="server" 
                                              AppendDataBoundItems="True" 
                                              DataSourceID="GetMachineModel" 
                                              DataTextField="Name" 
                                              DataValueField="ID"                                               
                                              Height="21px" 
                                              Width="217px">
                                <asp:ListItem Enabled="true" 
                                              Text="Select a Machine Model."
                                              Value="NULL">
                                </asp:ListItem>
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label2" 
                                       runat="server" 
                                       Text='<%# Bind("MachineModel") %>'>
                            </asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:CommandField ButtonType="Button" ShowEditButton="True" />
                </Columns>
                <FooterStyle BackColor="Transparent" />
                <PagerStyle BackColor="Transparent" 
                            ForeColor="Black" 
                            HorizontalAlign="Left" />
                <SelectedRowStyle BackColor="Transparent" 
                                  Font-Bold="True" 
                                  ForeColor="White" />
                <HeaderStyle BackColor="Black" 
                             Font-Bold="True" 
                             ForeColor="White" 
                             HorizontalAlign="Center" />
         </asp:GridView>

Where the problem seems to lie, is in this area below:

<asp:TemplateField HeaderText="Machine Type" 
    SortExpression="MachineType">
    <EditItemTemplate>
        <asp:ObjectDataSource ID="GetMachineType" 
            runat="server" 
            SelectMethod="GetMachineTypeList" 
            TypeName="Datamart.UI.Reporting.Web.FilteredReportInputsSvc.FilteredReportInputsService">
            <SelectParameters>
                <asp:Parameter Name="siteid" Type="String" />
            </SelectParameters>
        </asp:ObjectDataSource>
        <asp:DropDownList ID="MachineTypeDropDown" 
            runat="server" 
            DataSourceID="GetMachineType"
            DataTextField="Name"
            DataValueField="ID"                                               
            Height="21px" 
            Width="217px"
            AppendDataBoundItems="true">
            <asp:ListItem Enabled="true"
                Selected="True"
                Text="Select a Machine Type.">                                 
            </asp:ListItem>
        </asp:DropDownList>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label1" 
            runat="server" 
            Text='<%# Bind("MachineType") %>'>
        </asp:Label>
    </ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Machine Model" 
    SortExpression="MachineModel">
    <EditItemTemplate>
        <asp:ObjectDataSource ID="GetMachineModel" 
            runat="server" 
            SelectMethod="GetMachineModelList" 
            <asp:TemplateField HeaderText="Machine Type" SortExpression="MachineType">
                    <EditItemTemplate>
                        <asp:ObjectDataSource ID="GetMachineType" 
                                              runat="server" 
                                              SelectMethod="GetMachineTypeList" 
                                              TypeName="Datamart.UI.Reporting.Web.FilteredReportInputsSvc.FilteredReportInputsService">
                            <SelectParameters>
                                <asp:Parameter Name="siteid" Type="String" />
                            </SelectParameters>
                        </asp:ObjectDataSource>
                        <asp:DropDownList ID="MachineTypeDropDown" 
                                          runat="server" 
                                          AppendDataBoundItems="True" 
                                          DataSourceID="GetMachineType" 
                                          DataTextField="Name" 
                                          DataValueField="ID"                                               
                                          Height="21px" 
                                          Width="217px">
                            <asp:ListItem Enabled="true" 
                                          Text="Select a Machine Type.">
                            </asp:ListItem>
                        </asp:DropDownList>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label1" 
                                   runat="server" 
                                   Text='<%# Bind("MachineType") %>'>
                        </asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Machine Model" SortExpression="MachineModel">
                    <EditItemTemplate>
                        <asp:ObjectDataSource ID="GetMachineModel" 
                                              runat="server" 
                                              SelectMethod="GetMachineModelList" 


TypeName="Datamart.UI.Reporting.Web.FilteredReportInputsSvc.FilteredReportInputsService">
                            <SelectParameters>
                                <asp:Parameter Name="siteid" Type="String" />
                            </SelectParameters>
                        </asp:ObjectDataSource>
                        <asp:DropDownList ID="MachineModelDropDown" 
                                          runat="server" 
                                          AppendDataBoundItems="True" 
                                          DataSourceID="GetMachineModel" 
                                          DataTextField="Name" 
                                          DataValueField="ID"                                               
                                          Height="21px" 
                                          Width="217px">
                            <asp:ListItem Enabled="true" 
                                          Text="Select a Machine Model."
                                          Value="NULL">
                            </asp:ListItem>
                        </asp:DropDownList>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label2" 
                                   runat="server" 
                                   Text='<%# Bind("MachineModel") %>'>
                        </asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>

Updated for bounty

My overall problem is: using the gridview, I am unable to get my edit, update, cancel buttons to work. So what I would like to also know since I am throwing a bounty on this is: how can I get these events to work properly using ObjectDataSources?

I already know that the web services work properly, I just do not know how to load the necessary parameters with the right data-values from the table. Any help or suggestions are greatly appreciated.

Error thrown at the moment:

Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

I am unsure as to how to get the update and cancel events to fire correctly, so I have been trying to use the OnRow* event handlers, but none of these work or fire, even when I set up a break point on a method just to see if the event will fire.

Update2

So as requested here is what i have for the code behind dealing with the the events i had thought might fire, (note: i've tried this with almost all of the other events). When i would run a debugger attaching the page to an asp.net process and click on the update button, cancel button, or edit button i would expect the page to go to the breakpoint, however this does not happen.

Note: I also know that the code behind is most likely incorrect, but i didn't want to fix any of that until i knew which event would be the right one that fires for update and cancel buttons.

    protected void GridViewHolder_Updating(object sender, GridViewUpdateEventArgs e) 
{

    int machineid;
    string machineTypeid;
    string machineModelid;

    GridViewRow row = (GridViewRow)GridViewHolder.Rows[e.RowIndex];
    Label id = (Label)row.FindControl("ID");
    DropDownList mType1 = GridViewHolder.Rows[e.RowIndex].FindControl("MachineTypeDropDown") as DropDownList;
    e.NewValues["MachineType"] = mType1.SelectedValue;
    DropDownList mType = (DropDownList)row.FindControl("Machine_Type");
    DropDownList mModel = (DropDownList)row.FindControl("Machine_Model");

    machineid = Convert.ToInt32(id);
    machineTypeid = mType.DataValueField.ToString();
    machineModelid = mModel.DataValueField.ToString();

    inputsService.UpdateMachineTypes(machineid, machineTypeid);
    inputsService.UpdateMachineModels(machineid, machineModelid);

}

protected void GridViewHolder_Updated(object sender, GridViewUpdatedEventArgs e)
{

}

/// <summary>
/// Handles the Click event of the cancel button under edit in the gridview control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewCancelEditEventArgs"/> instance containing the event data.</param>
protected void GridViewHolder_Canceling(object sender, GridViewCancelEditEventArgs e)
{
    //reset the edit index
    GridViewHolder.EditIndex = -1;
    //Bind data to GridViewHolder
    BindData();
}

protected void GridViewHolder_Editing(object sender, GridViewEditEventArgs e)
{

}
#endregion

#region Private Methods

private void BindData()
{
    GridViewHolder.DataSource = Session["MachineTable"];
    GridViewHolder.DataBind();
}

#endregion

Update 3

Okay you will find above the most recent attempt that i have done to try and get the update and cancel buttons to function properly in the gridview.

Any help or suggestions are greatly appreciated.

Thank you.

Suman Banerjee
  • 1,923
  • 4
  • 24
  • 40
James213
  • 957
  • 5
  • 31
  • 57
  • Could you provide the exact exception message? – Wiktor Zychla Nov 21 '11 at 14:52
  • @WiktorZychla I updated the question with the desired information you were looking for. – James213 Nov 21 '11 at 15:27
  • There is a similar question posted here [Binding dropdown list in a gridview edit item template](http://stackoverflow.com/questions/621536/binding-dropdown-list-in-a-gridview-edit-item-template). I hope this helps you. Regards Amit – Amit Rai Sharma Nov 21 '11 at 17:45
  • I have an idea what it might be. To confirm first, please could you add something else to your page which would cause a postback outside of the DataGrid itself (e.g., a button with an OnClick serverside event handler) - please let me know if clicking the button causes the viewstate error or not (try clicking it both with and without the 'edit' mode being enabled on the DataGrid to be sure). Thanks – Alex Norcliffe Nov 23 '11 at 20:58
  • @AlexNorcliffe I have tried this in fact when working on other sections of my page: When i am out of the edit mode (ie did not click the edit button) it the page works fine. But after clicking the edit button the page ends up being locked by that viewstate error. Thus clicking one of my other buttons on the page will throw the viewstate error when the gridview is stuck in edit mode – James213 Nov 23 '11 at 21:18

3 Answers3

2

I would suspect that the ViewState error is being caused by code on the code-behind and is not being triggered by the GridView code you posted. Can your post the code-behind for your OnRow... methods and any Page_Load/Page_Init code?

Having said that, in order to get your updates to work for the DropDownList controls you'll need to add some code in the RowUpdating method. Here's a blog post by Peter Kellner, but the pertinent code is:

protected void GridViewIncomingUrls_RowUpdating(object sender, GridViewUpdateEventArgs e) { 
        DropDownList dropDownListUser = GridViewIncomingUrls.Rows[e.RowIndex].FindControl("MachineTypeDropDown") as DropDownList;
        e.NewValues["MachineTypeID"] = dropDownListUser.SelectedValue;
}

Also, you may want to set the SelectedValue property of your dropwdowns, so that the previously selected value is pre-populated when the user hits the edit button:

 <asp:DropDownList 
    ID="MachineModelDropDown"  
    SelectedValue='<%#Bind("MachineModelID") %>'
    ...
Chris Van Opstal
  • 36,423
  • 9
  • 73
  • 90
  • I added the code behind you requested, but when using rowupdating my problem seems to be that it wouldn't go to the code behind for that method when i had implemented it. – James213 Nov 21 '11 at 19:16
  • `OnRowEditing="GridViewHolder_Editing" OnRowUpdated="GridViewHolder_Updated" OnRowUpdating="GridViewHolder_Updating"` - Are these methods defined in your code behind? – Leon Nov 22 '11 at 16:23
  • @Leon I do have these methods defined in my code behind, however the only method that fires is `onRowEditing="GridViewHolder_Editing" ` However, this method is only declared with nothing inside because i am unsure as to what i am suppose to put within this method. – James213 Nov 22 '11 at 21:32
2

I've never seen an ObjectDataSource used inside a template - always controls explicitly populated / bound in ItemDataBound event of the grid.

Complex stuff like this, I would only use an ItemTemplate and then have all the controls (Label and DropDown in your case) inside that. Each would be toggled based on Grid.EditIndex > -1.

I would start by commenting out parts of the grid (like that whole piece with ObjectDataSource inside an EditTemplate) and see if that works.

If that dropdown / field is the culprit, then I'd re-work it to be populated inside Grid_ItemDataBound() event instead of inside markup.

Leon
  • 3,311
  • 23
  • 20
  • Just to make sure i fully understand, What i should have in the edittemplate section is the `dropdownlist` only. Right now i've removed the `objectdatasource` from the template and removed the 'asp:listitem' from the 'dropdownlist' as well. so right now what should come up when i press the edit button in my table is an empty/un-populated `dropdownlist` correct? – James213 Nov 22 '11 at 22:49
  • Or do you mean That i should get rid of the `Objectdatasource` and move the `dropdownlist` from the `edititemtemplate` to the `itemtemplate`? – James213 Nov 22 '11 at 23:02
  • Completely remove ObjectDataSource from the template. In the ItemTemplate put both: dropdown and list. Then in the ItemDataBound handler you can check if this item is being edited, and show/hide/bind dropdown or list as needed: `e.ItemIndex == Grid.EditIndex` will tell you if this current row is in edit mode. – Leon Nov 23 '11 at 14:21
0

One possible solution would be to enable the viewstate to false as so:

EnableViewState="false"

The links below will be of some help.

http://forums.asp.net/t/1159585.aspx/1

http://forums.asp.net/t/1295517.aspx/1

James213
  • 957
  • 5
  • 31
  • 57
Rohit
  • 165
  • 4
  • surprisingly this actually did the trick. Now the viewstate error does not come up anymore. **although**, i am unsure as to if this will cause any problems in the future. Now the only step i am stuck on is how to trigger the update event. – James213 Nov 28 '11 at 19:49