I'm trying to loop through a gridview and save all the items in it at once. However I have a problem getting the values from the dropdownlist and textbox. I get this error each time:
ArgumentOutOfRangeException was caught. Specified argument was out of the range of valid values.
Here's the code I'm using:
foreach (GridViewRow gvr in gvInvalidOrgs.Rows)
{
try
{
org_code = Convert.ToInt32(gvr.Cells[0].Text);
division = ((DropDownList)gvr.Cells[1].Controls[0]).SelectedValue;
org_description = (((TextBox)gvr.Cells[2].Controls[0]).Text);
}
...
}
Both the textbox and the dropdownlists are dynamically created on rowbound if that matters.
TIA
Without knowing precisely which line the exception is thrown on, it's hard to diagnose with equal precision, but what's likely happening is that you're looking for a control in a cell that doesn't have any controls.
How could this come about? Well, since you are creating the controls in RowDataBound, if you don't bind your grid on every postback (and I'm not recommending that you do) your dynamically-added controls won't be recreated on postback. The posted data will include values for those controls, and ViewState will contain data for those controls, but if you don't recreate those controls on every postback, those controls won't exist when you attempt to access their values.
But you don't have to rebind to recreate the controls. As Mr. Schmelter says in his comment, if you move your creation of the controls from the RowDataBound to the RowCreated event handler, they will be created when the grid rows are re-created on postback.
Related
I use GridView & Repeater (and other like DropDownList) controls extensively in my application along with ObjectDataSource components and classes that serve data for ObjectDataSource (TypeName / SelectMethod attributes on ObjectDataSource). I recently noticed that SelectMethod is only called when
IsPostBack == false
Also, when I bind manually, I always bind when !IsPostBack. I never was curious how controls maintain their data between postbacks, until now (I have to create GridView with sorting/pagination etc and I want to do it efficently).
Could you explain / provide some links with descriptions how it's done?
Also I don't get one thing: when working with GridView and I iterate over rows, sometimes I need to access its GridViewRow.DataItem property in order to get backing object (usually to get some kind of ID). And sometimes it's null - sometimes not. I couldn't figure out why. However then it's null, I still can access (for instance) GridViewRow.DataKeys.
Thanks
EDIT: know when answers say that it thanks to ViewState, I have another question: If I data bind 100 business objects which are pretty heavy and I only use a few properties while data binding (let's say I also use OnRowDataBound event to render some additional data), does it mean that whole objects are serialized?
ASP.Net uses ViewState a hidden variable in the all HTML pages to maintain state of a page.
Reasd this for more understanding
http://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&sqi=2&ved=0CFMQFjAB&url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fms972976.aspx&ei=UpE0UK3uBsOqrAe94ICwBg&usg=AFQjCNG5ErbrFH0ZYV_WW-jonIl25xEsDQ
They store it in a hidden field on the page called ViewState (or more precisely "__VIEWSTATE"). If you do a View Source on your ASPX page, you'll see it.
You too can store and retrieve state information for your page in the ViewState by accessing the ViewState property of your Page.
I'd start here http://msdn.microsoft.com/en-us/library/ms972976.aspx
So, yes, if you store a large number of large objects, there is a large amount of data being transferred to and fro to the client in the page cycle. Used carefully, Viewstate can be useful, but used carelessly, it can have negative effects.
I have a GridView control on my page which is connected with ObjectDataSource where TypeName="BLL.MyLogic" DataObjectTypeName="BLL.MyObject" UpdateMethod="MyUpdateMethod".
The update in MyUpdateMethod is conditional which I am checking the conditions before _datacontext.submitchanges(). Depending on my check I throw exceptions like ("not unique") or ("no appropiate logic found") etc. I am catching these exceptions at page level via OnUpdated="MyDataUpdated" of my ObjectDataSource.
These operations just work fine. Problem is after the process is done and even in the case of "exception occured" the GridView gets reloaded and editindex = -1 (initiated). Even if I manually retrieve the editindex and make it editable the form data (data input by user) in the edittemplate gets wipped away. ViewState doesnt work here.
What is the work around to this situation ?
Thanks in advance.
Have you tried setting the GridViewUpdatedEventArgs.KeepInEditMode property to true in your RowUpdated event handler?
While going through some of the code, i found there is written like this:
ListViewDataItem dataItem = (ListViewDataItem)(((ImageButton)sender).Parent.Parent);
int noteId = Convert.ToInt32(((HiddenField)dataItem.FindControl("hidNoteId")).Value);
Please explain the meaning of these two line.
There is a control (typed to hidden field) that is being used to track the identity of item within a ListView (http://msdn.microsoft.com/en-us/library/bb398790.aspx)
And it's code that shouldn't be written, IMO. It's inefficient and brittle. Also, the identity of the item is stored in plain text in the source of the page.
This code appears to be getting the identity of a databound item when a button is clicked. A better way would be to simply set the command arguments of the button, like so:
<asp:ImageButton runat="server" CommandArgument="[Binding Expression]" />
In the event handler for the button, the CommandArgument can be retrieved and converted to an Int32. With this methodology, you shouldn't even need that hidden field.
Firstly, both the lines seem a bit crazy in their use of brackets and casting. There's probably a better way to do what they're doing, but without more code it's difficult to offer any suggestions.
Anyway, the first line is going to be in an event handler for an event raised by an ImageButton. The event handler method will have a sender argument; this is being cast to an ImageButton. Then Parent.Parent is called on this ImageButton; this will give the object two levels up in the control heirarchy. The developer is obviously quite sure this is a ListViewDataItem, so it's being cast to one of these. Therefore the variable dataItem now contains an instance of a ListViewDataItem.
In the second line, the FindControl method is being called on dataItem. There is presumably a control under this ListViewDataItem with an ID of "hidNoteId". FindControl returns a Control; but the developer knows this control is actually a HiddenField, so there's a cast. The Value property of this hidden field is then passed into the Convert.ToInt32 method to give an integer - this is then stored in the noteId variable.
So at the end of it all, there's a ListView, in which each data item contains a hidden field that contains the value of some ID. This code is getting the ID.
dataItem is a bound control, which when clicked is being used to represent a placeholder. This is used to identify which line is being executed within in the control.
By looking for a parent's parent of this control, it's giving the code a starting point to navigate to the correct row to extract a value from.
After the row is found, the noteId is being assigned a hidden value and cast into an integer.
When items are bound to a grid/repeater, with a button as the post-back control, a way is needed to identify which row is being executed. All the code is doing above is navigating the control and extracting a value from a set of values within the row.
I've two issues currently preventing me from finishing two projects properly. I'll put them both here as I believe they're connected to the asp.net page lifecycle, but I can't find a way around them.
First I have a DropDownList which I must sort in codebehind. It only contains text, so I should be able to do that with the following method called in page load:
Dim alist As ArrayList = New ArrayList
For Each litem As ListItem In ltEsittelyDropDownList.Items
alist.Add(litem.Text)
Next
alist.Sort()
Dim uusiDDList As New DropDownList
For i As Integer = 0 To alist.Count - 1
Dim litem As New ListItem
litem.Text = alist(i).ToString
litem.Value = alist(i).ToString
uusiDDList.Items.Add(litem)
' Response.Write(alist(i).ToString)
Next
ltEsittelyDropDownList = uusiDDList
ltEsittelyDropDownList.DataBind()
As you can see, there's a commented response.write in there, which shows the list is actually sorted. So why, when I load the page, can't I see any effect?
The other problem, which is more critical and difficult, is as follows:
In the aspx page I'm binding a SQL Server 2005 datasource to a gridview. And in the code-behind I catch on to the RowDataBound event in which I handle some links and properties inside the gridviews' cells. But I cannot get this to work on the first page load, only after the first extra postback.
So, what is there to do? And thanks for all advice in front!
Your first problem is calling DataBind on a control you have filled manually. You likely have a DataSource specified in the control declaration, which is being used when DataBind is called. You can simplify the code by just adding the list items to the original control:
For i As Integer = 0 To alist.Count - 1
ltEsittelyDropDownList.Items.Add(New ListItem(alist(i).ToString())
Next
Alternatively, as you have a collection already, you can just bind it to the control:
ltEsittelyDropDownList.DataSource = alist
ltEsittelyDropDownList.DataBind()
For your second problem, some example code would help - specifically, where and how the control is databound and the code in RowDataBound.
1) Suppose GridView1 is bound to ObjectDataSource and that GridView1.SelectedIndex is set to value 7. If we then rebind GridView1 by calling GridView1.DataBind(), GridView.SelectedIndex will still retain its initial value ( 7 ).
Are there any other properties which GridView remembers across rebinding operations?
2) Suppose GridView1 is bound to ObjectDataSource control. When GridView1’s row gets deleted, we can call GridView1.DataBind() inside GridView1.RowDeleted event handler to retrieve values from data source. If we don’t call Gridview1.DataBind inside that event handler, then DataBind() will automatically be called by Asp.Net and the result will be the same.
So are there any reasons why we should manually call GridView.DataBind( inside RowDeleted event handler ) instead of letting Asp.Net call it automatically?
Your answer lies in Page.DataBind and Control.DataBind methods.
The main difference is that all data sources are bound to their server controls after the Page.DataBind method is called. No data is rendered to the control until you explicitly call either the DataBind method of the Web server control or until you invoke the page-level Page.DataBind method. Typically, Page.DataBind (or DataBind) is called from the Page_Load event.
Source
Particular answer for 1) is there's no such property for GridView,but you can make your own one and add last changed control.(Ideal)
For 2)Your action here coming from a postback,because the default bound source is changed after all you deleted a row inside it,since default source cannot be bound again,you need to call DataBind manually.
I'm going to mention a bit about Hierarchical Data Binding for starters.
In order to bind a datasource to a server-side control (GridView,DetailsView,.. etc) , that control must support a property known as DataSource and a method known as DataBind() , and the datasource that control is bound implement IEnumerable interface.
There is an exception for DataSet and DataTable which can be both bound directly , which results in binding to the default DataView of default table.
To bind a data to a control , you assign the data source to the DataSource property of the control and call its DataBind() method.Source
Since in your case ,databinding situation is different as you mentioned earlier that you bind GridView with ObjectDataSource which executes a query in page load and in every SELECT,INSERT,UPDATE,DELETE operations,datasource is bound automatically (which means DataBind is also called automatically).
There is another case which you are looking for an answer in the first place is that if datasource is queried and bound in page events (i.e. you query something and get a result with DataTable and bind it into GridView --> this source is not in the page not a objectdatasource or something else stands on page as static source).Since this query is coming from an event,when you enable pageIndex you must query it again that leads to you must also bind it with DataBind.
DataTable sourceTable = GetDataFromServer();
gridView.DataSource = sourceTable;
gridView.DataBind();
I hope that you can understand this time.