Last post Dec 12, 2014 03:15 PM by mmodrall
Dec 05, 2014 04:30 PM|mmodrall|LINK
I've seen a lot of posts about how squirrely GridViews can be in UpdatePanels, but I've been nursing along an old implementation I was handed. Lately the PM wanted to spiff it up a little, so I've been adding some cosmetic features, and it was going fine
until I added a drop-down to change the number of results on the page. Then I started getting viewstate load errors about the control tree not matching.
We've got a search form with a bunch of different filters and a Search button on the main form and the Search button is a trigger for the UpdatePanel containing the results.
First they wanted the total count of results in the pager of the GridView. Fine, I added that.
Next they wanted a checkbox in the filters section to control whether to display the total in the pager or not (because they were concerned about the cost of the extra query to get the real total). I added that, and it worked without problem.
Then I added a dropdown to let the user change the number of rows/page. Now any time you change any filter *after* 1 pageview with the new result count you get the viewstate load error.
What puzzles me is that I can change filters that result in a different row count or no results at all (e.g. First Name) and click Search as many times as I like and I don't get a viewstate load error. I can check and uncheck the box to show the
count in the pager (resulting in diddling of the pager rows) and click Search as often as I like and I don't get a viewstate load error.
But changing the dropdown that changes the GridView.PageSize and then it gets very brittle and starts throwing viewstate load errors. That's what puzzles me at the moment.
The code change was to set
ResultGV.PageSize = int.Parse(ResultCount.SelectedValue);
just before selecting and binding the gridview in the Search button OnClick function.
Dec 07, 2014 09:27 PM|Archer Wang|LINK
Based on your post, I made a test on my computer, but it worked fine. It's hard to provide any suggestion with the information provided.
I suggest that you can press F12 to debug , and check if your page has any error message or details.
Or you could refer to the below link.
If you have any other concern about it, please feel free to let me know.
Dec 08, 2014 12:14 PM|mmodrall|LINK
Thank you for taking the time to respond...
I've read the 2 links, and the only controls that would be getting added/removed dynamically that I can think of would be the pager row controls. The thing that puzzles me is that changing *other* fields would have the same effect, but those queries don't
result in viewstate load errors.
For example, checking/unchecking the Show Count checkbox would result in those display controls appearing or not. Changing the First or Last Name filter would result in different pager controls (when the new search only produces a single page of results,
say). But those changes don't result in a viewstate load error.
I did attach the debugger, and the exception I see is deep in the ASP.Net bowels with a failure to cast an ArrayList to a Pair. But with all the context optimized away, it's hard to get much context on which viewstate element it's trying to load. It's
about 15 levels deep in LoadViewStateRecursive from our master page.
The actual formatting of our pager string is done in the DataBound event of the GridView; not sure if that's the right place to do it, but there we're not dynamically adding/removing controls; we check if the pager controls are present, and if they are we
set the visible or not based on the configuration.
If you put together a quick sample, I would appreciate seeing it, if that's not a problem for you.
Dec 08, 2014 06:36 PM|mmodrall|LINK
I've been playing with it a lot more today and am still not quite there on getting the behavior, but I did find that the viewstate exception was happening trying to read a Panel in the top pager row.
Some background on what we're doing: We have a checkbox that determines whether or not to display the total result count. That result count, when displayed, is supposed to be in the left corner of the pager while the pager buttons and controls are right-justified.
The default template in our skin looked like this:
<asp:Panel runat="server" id="countPanel" HorizontalAlign="left" CssClass="paginationDiv" style="float: left;" Visible="false">
<asp:Literal runat="server" ID="countString"/>
<asp:Panel runat="server" id="pagerPanel" HorizontalAlign="right" CssClass="paginationDiv" style="float: right;">
<asp:ImageButton ID="firstPButton" runat="server" ImageUrl="~/images/icoRWEnd.gif" CommandArgument="First" CommandName="Page"/>
<asp:ImageButton ID="prevPButton" runat="server" ImageUrl="~/images/icoRWOne.gif" CommandArgument="Prev" CommandName="Page"/>
<asp:Literal runat="server" ID="pagerString" />
<asp:ImageButton ID="nextPButton" runat="server" ImageUrl="~/images/icoFFOne.gif" CommandArgument="Next" CommandName="Page" />
<asp:ImageButton ID="lastPButton" runat="server" Visible="false" ImageUrl="~/images/icoFFEnd.gif" CommandArgument="Last" CommandName="Page"/>
Panels used for grouping and float-left and float-right styles to achieve the visual effect
Our GridView has a DataBound event handler that fills in and/or hides the
countString and pagerString panels (the DataBound event presumably because that's the earliest point when we know the answers).
When I found that the viewstate error was happening on the countPanel, I tried setting countPanel.EnableViewState = false; in the DataBound handler but that didn't stop the problem.
I added EnableViewState = false to the template on the contentPanel, and that *did* stop the problem.
So is the DataBound handler running at the wrong place in the life cycle to impact the viewstate correctly?
http://msdn.microsoft.com/en-us/library/ms972976.aspx discusses the page lifecycle vis a vis viewstate but the specifics of when Gridview events happen in there isn't immediately clear.
Dec 12, 2014 03:15 PM|mmodrall|LINK
Okay, this was weird...
If you set the pager row.ID in the DataBound event then the pager gets very brittle and unreliable.
Our old code only expected 1 pager row (implicitly disallowed PagerSettings.Position == TopAndBottom) and set the ID of the row in an InitializePagerRow() override. You don't want 2 html items with the same id, but InitializePagerRow() doesn't give you
any straight-up sign which row you're working on at the moment, and TopPagerRow/BottomPagerRow aren't initialized yet.
So I moved the id setting to the DataBound event handler where we were filling in the pager text...
I noticed that even our pages that *weren't* trying to implement on-the-fly pagesize changing had the pager broken and I started backing out things a bit at a time until I found it was setting the row id that was making everything nuts.