ASP.NET GridView Paging Not Working - asp.net

I have searched through stack overflow and Google but I could not find an answer that would work for my situation and I tried a lot of them.
I have an issue with an ASP.NET gridview. When the page first loads the grid is attached to a Data Source ID and displays the records with paging that works.
Now if the user filters the data the first page of returned records is displayed but if they click on 'Page 2' in the gridview footer the page flashes but does not change the data or pages.
Also I have noticed that when the search is applied there are 10 plus pages displayed in the footer no matter how many records are returned.
Here is the ASP.NET GridView header code:
<asp:GridView ID="gvSOHeader" runat="server"
AutoGenerateColumns="False" Width="1010px" CellPadding="4"
ForeColor="#333333" GridLines="Horizontal" AllowSorting="True"
AllowPaging="True" OnPageIndexChanging="gvSOHeaderOnPageIndexChanging"
PageSize="15" DataSourceID="SqlDataSource2">
When the user searches here is the code that reassigns the grid view datasource:
Using conn As New SqlConnection(myConnection)
conn.Open()
Using sqlCmd As New SqlCommand
sqlCmd.CommandText = strText
sqlCmd.Connection = conn
Using sqlDA As New SqlDataAdapter(sqlCmd)
Using sqlDT As New DataTable
sqlDA.Fill(sqlDT)
If sqlDT.Rows.Count > 0 Then
gvSOHeader.DataSourceID = String.Empty
gvSOHeader.DataSource = Nothing
gvSOHeader.DataSource = sqlDT
gvSOHeader.DataBind()
End If
End Using
End Using
End Using
conn.Close()
End Using
This works but only is as far as it displays the first page of returned results. I can not page to any other results page.
Here is the OnPageIndexChanging event code:
Protected Sub gvSOHeaderOnPageIndexChanging(sender As Object, e As GridViewPageEventArgs) Handles gvSOHeader.PageIndexChanging
gvSOHeader.PageIndex = e.NewPageIndex
gvSOHeader.DataBind()
End Sub
I have also noticed that the OnPgeIndexChanging event fires twice but I do not know why. I tried adding an If statement to the OnPageIndexChanging to check for Not IsPostback but it still will not display more than the first page of searched data.
I am sorry if this is a duplicate but I could not find a result that fit my situation. Any help would be very greatly received.
Thanks.

Related

how to pass textbox value in asp.net to a code on update click

I have an issue with the following code, the markup is as follows:
<asp:GridView ID="GridView" runat="server"
AutoGenerateEditButton="True"
OnRowDataBound="GridView_RowDataBound"
OnRowEditing="GridView_RowEditing"
OnRowUpdating="GridView_RowUpdating"
CssClass="gridv">
<Columns>
<asp:TemplateField HeaderText="ASN">
<ItemTemplate>
<asp:Label ID="lblASN" runat="server" Text='<% #Eval("ASN")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtASN" runat="server" Text='<%# Bind("ASN")%>' CssClass="form-control"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
...
However when I run this code to get the new changed values from the textboxes that were successfully generated and populated, I only get the initial values not the news that user has entered, the code behind this is:
Protected Sub GridView_RowUpdating(sender As Object, e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView.RowUpdating
Try
Dim row As GridViewRow = GridView.Rows(e.RowIndex)
Dim ID As Integer = DirectCast(row.FindControl("txtID"), TextBox).Text
Dim sASN As String = DirectCast(row.FindControl("txtASN"), TextBox).Text
Dim sDescription As String = DirectCast(row.FindControl("txtDescription"), TextBox).Text
Dim sManufacturer As String = DirectCast(row.FindControl("ddlmanufacturer"), DropDownList).SelectedValue
GridView.EditIndex = -1
Catch
End Try
ShowEmpDetails()
End Sub
So when I click the update button I use a message box to write the variables above and the values that I get are the same ones that got initially written to the textboxes, not the text that the user has changed?
I have worked out this code from a similar example in which this works with no issues, I honestly can not figure out what I am doing wrong?
As requested Page_Load event is calling this function:
Private Sub ShowEmpDetails()
Dim query As String = "SELECT * from inventory.all_items"
Dim cmd As MySqlCommand
cmd = New MySqlCommand(query)
cmd.Connection = myConn
Dim sda As New MySqlDataAdapter
sda.SelectCommand = cmd
Dim dt As New DataTable
sda.Fill(dt)
GridView.DataSource = dt
GridView.DataBind()
End Sub
Ok... there are so many things wrong with your coding approach that I don't know where to begin. Sorry.
Lets' start again and I'll explain how to properly pass values between the DOM and your code-behind.
Firstly, you need to understand how the DOM populates and builds the HTML for the browser to know what's going on.
I would test your project in Firefox and use the Inspector tool (right-click wep page). That tool is gold and has saved my already bald-head from revealing my skull!! :-)
As you know, the GridView control binds both the "view" and "edit" portions of the control into the same code. I can see you have Eval() for the view portion of the control (or the mode of the control I should say) and you have Bind() for the Edit mode. That is good. I personally hate BoundControls, as you cannot really see what's going on under the hood.
Next, avoid using AutoPostBack like the plaque! It's just ugly.
Get familiar with AjaxControlToolKit (there are others too, but start with the Ajax), and the ASP:UpdatePanel.
So in your case something like this ...
<asp:UpdatePanel ID="upADDMAIN" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="GridView" runat="server"
AutoGenerateEditButton="True"
OnRowDataBound="GridView_RowDataBound"
OnRowEditing="GridView_RowEditing"
OnRowUpdating="GridView_RowUpdating"
CssClass="gridv">
Try and put as much functionality back into the defaults of the GridView control. So go back to your DESIGNER mode in VStudio and add all the functionality you need like EDIT, UPDATE, DELETE, etc in the design mode of the GridView. This will also make sure your SQLDataSource is updated at the same time with the right SQL for the task.
Now why are you using OnRowEditing and OnRowUpdating?
My rule-of-thumb is always to keep things to a minimum and give as much control to ASP.net as possible. This avoids re-inventing the wheel with code-behind stuff that ASP.net can handle straight out of the box.
I generally use OnDataBound(), OnRowDataBound(), and OnRowUpdating() to both read the data and pre-UPDATE the data before the Update() gets called by the controls.
ie:
protected void gvLogins_RowDataBound(object sender, GridViewRowEventArgs e)
{
GridViewRow gvRow = (GridViewRow)e.Row;
{
if (gvRow.RowType == DataControlRowType.DataRow)
{
and
protected void gvLogins_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//apply values to the SQL parameters for UPDATE, etc
GridViewRow gvRow = (GridViewRow)gvLogins.Rows[e.RowIndex];
to do some pre-Update updates outside of the GridView for example.
I never do prerendering or preloading of data in the PageLoad(). That is just re-inventing the wheel, when by default most ASP.net controls already have connectivity and updating built in!
Oh and to get the values of controls inside a GridView... just use FindControl() but in the right place! ie: the DataBound() events etc.
DropDownList ddlAgent = (DropDownList)gvRow.FindControl("ddlAgent");
HiddenField hfAgentID = (HiddenField)gvRow.FindControl("hfAgentID"); //from overall state,as EDIT mode defaults the hfAgentID to 0!
if (ddlAgent != null && hfAgentID != null)
ddlAgent.SelectedValue = hfAgentID.Value;
Sorry I only use C#, not VB.
Good luck.

ASP.NET Basic GridView control not displaying at all

I am getting started with a basic asp.net gridview control and I just dont seem to be able to make it visible in the web browser at all in an asp.net web application.
Here is what I have just to get myself started off. In the aspx page ...
<asp:GridView ID="myGr" runat="server" BackColor="Aqua" AutoGenerateColumns="True" Width="100%" ViewStateMode="Enabled"></asp:GridView>
In the code behind I have ...
Dim tbl As New DataTable
tbl.Columns.Add("ID", GetType(Int32))
tbl.Columns.Add("Name", GetType(String))
tbl.Columns.Add("Birthday", GetType(Date))
Dim pers As DataRow = tbl.NewRow
pers("ID") = 1
pers("Name") = "Tim"
pers("Birthday") = New Date(1973, 6, 9)
myGr.DataSource = tbl
myGr.DataBind()
Would be great if anyone could give me some basic advice on this control
You need to add the row you inserted to the datatable tbl. Because you haven't done this, the datatable is empty so the Gridview is empty too.
Like that: tbl.Rows.add(pers)
You create row but you do not add it to the table.
You have to add line like that:
tbl.Rows.Add(pers)

ASP.NET Losing listbox binding on viewchange?

Ok so what seems like a basic problem is getting the better of me and my exstensive google efforts have come up short. Perhaps I don't understand enough to ask the right questions.
Here's my problem:
I have a formview control, or rather a series of them, each page displaying entry from previous forms, for a higher level access to approve/edit as needed. So, on form "B", I have the contents of form "A" and the blank part of "B" to filled out...So two seperate fromviews on the page.."A" and "B"
That works fine, the issue is when I change the mode to edit previous entry. So if I have a button or the default linkbutton to change from ReadOnly to Edit I not only lose bindings but any efforts to counteract that have left me with issues when I postback.
DUE TO LENGTH I'M LEAVING SOME CODE OUT
On my button I'm using FormView2.ChangeMode(FormViewMode.Edit) to change view, the default link button I've not changed
Bindings on my listboxes are setup like:
If Not Page.IsPostBack Then
'pulling bindings from table
cmd = New OleDbCommand("SELECT * FROM mslToi", objCon)
objReader = cmd.ExecuteReader
lst1.DataValueField = "listing"
lst1.DataTextField = "listing"
lst1.DataSource = objReader
lst1.DataBind()
'pre-selecting input data from form "A"
cmd = New OleDbCommand("SELECT [type_of_injury] FROM S2childToi WHERE ID = " & qs & "", objCon)
objReader = cmd.ExecuteReader
Do While objReader.Read
For Each y As ListItem In lst1.Items
If y.Text = objReader.Item(0) Then
y.Selected = True
End If
Next
Loop
end if
In the page load event.
MARKUP FOR THE FORMVIEW AS ASKED
<asp:FormView ID="FormView2" runat="server"
Width="100%" DataSourceID="AccessDataSource4">
<ItemTemplate>
</ItemTemplate>
<EditItemTemplate>
</EditItemTemplate>
</asp:FormView>
'''that is the short and sweet of the formview markup as requested. It may also be worth noting that it doesn't matter what mode I start in, if I change modes it equals same result'''
That works fine so far...it's when I change view to Edit that my listbox appears to no longer be bound (controls appear but have no content). My thought is that obviously I'm blocking out my code from postback events (I have a reason for this). I can use this code (without the If Not Page.IsPostBack) to force the selections and bindings but whenever I postback they will defualt to the table data, which can't happen, each listbox needs to postback so I can check for a certain selection. So what happens is the user input is trumped. Short and sweet.
I'm sorry that I can't explain better, any advice is much appreciated. If I can asnwer any questions or post code let me know.
Try this:
<asp:FormView ID="FormView1" runat="server">
<ItemTemplate>
<asp:ListBox ID="ListBoxReadonly" runat="server"></asp:ListBox>
</ItemTemplate>
<EditItemTemplate>
<asp:ListBox ID="ListBoxEdit" runat="server"></asp:ListBox>
</EditItemTemplate>
</asp:FormView>
Then, in your FormView's databound event, bind the data into your listbox depending on the current view.
Protected Sub FormView1_DataBound(sender As Object, e As EventArgs) Handles FormView1.DataBound
Dim myListBox As ListBox
If FormView1.CurrentMode = FormViewMode.ReadOnly Then
myListBox = DirectCast(FormView1.FindControl("ListBoxReadonly"), ListBox)
ElseIf FormView1.CurrentMode = FormViewMode.Edit Then
myListBox = DirectCast(FormView1.FindControl("ListBoxEdit"), ListBox)
End If
If myListBox IsNot Nothing Then
myListBox.DataValueField = "listing"
myListBox.DataTextField = "listing"
myListBox.DataSource = GetListingData()
myListBox.DataBind()
' your pre-select code here...
End If
End Sub

Why is My GridView FooterRow Referencing the Wrong Row?

I have a GridView and, using a fairly common method, I'm using a FooterRow and TemplateFields to provide the missing insert ability. So far so good.
The footer contains a TemplateField with a LinkButton to provide the postback that does the insertion. In the handler for the LinkButton's click, the Insert() method is called on the ObjectDataSource that the GridView is bound to. The ObjectDataSource's insert parameters are populated in the handler for its Inserting event. The code for all of this (abridged) looks like this:
Markup:
<asp:GridView ID="gvComplexRates" runat="server" AutoGenerateColumns="False"
DataKeyNames="id" DataSourceID="odsComplexMileageRates"
EnableModelValidation="True" ShowFooter="True">
<Columns>
<asp:TemplateField ShowHeader="False">
:
:
<FooterTemplate>
<asp:LinkButton ID="addLinkButton" runat="server" CausesValidation="false"
CommandName="Insert" Text="Add"></asp:LinkButton>
</FooterTemplate>
</asp:TemplateField>
:
:
</asp:GridView>
Code Behind:
Private Sub gvComplexRates_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvComplexRates.RowCommand
Select Case e.CommandName
Case "Insert"
odsComplexMileageRates.Insert()
End Select
End Sub
Private Sub odsComplexMileageRates_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceMethodEventArgs) Handles odsComplexMileageRates.Inserting
Dim fuelTypeDropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddFuelTypeInsert")
Dim engineTypeDropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddEngineTypeInsert")
Dim rateTextBox As TextBox = gvComplexRates.FooterRow.FindControl("tbRateInsert")
Dim vatRateTextBox As TextBox = gvComplexRates.FooterRow.FindControl("tbVatRateInsert")
e.InputParameters("expense_type_id") = ddExpenseTypeSelect.SelectedValue
e.InputParameters("fuel_type_id") = fuelTypeDropDown.SelectedValue
e.InputParameters("engine_type_id") = engineTypeDropDown.SelectedValue
e.InputParameters("rate") = rateTextBox.Text
e.InputParameters("vat_rate") = vatRateTextBox.Text
End Sub
Two of the fields in my FooterRow are DropDownLists that are populated from other tables. Again this works fine and I can add, edit and remove rows without problem.
The problem comes when I use a modal dialog from this page to insert extra rows into the tables used to populate the DropDownLists in the FooterRow. The insert operations work fine and the modal dialog closes and at this point I use a javascript postback (basically a call to __doPostBack()) so that my FooterRow DropDownLists can be updated. The code for this is:
Protected Sub updateFuelEngineDropdowns()
odsFuelTypes.Select()
odsEngineTypes.Select()
Dim dropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddFuelTypeInsert")
dropDown.DataBind()
dropDown = gvComplexRates.FooterRow.FindControl("ddEngineTypeInsert")
dropDown.DataBind()
End Sub
This sub, updateFuelEngineDropdowns(), is called from the Page Load event. The first time I called it it worked fine. For some reason in subsequent runs through the debugger I'm getting NullReferenceExceptions. Digging into the debug object viewer it is apparent that the GridView FooterRow is referencing the row above the footer which contains no controls (at least not at this non-editing stage) and so, quite reasonably, gives my the Null reference.
The debug QuickView expressions I use are:
gvComplexRates.FooterRow.Controls(3)
DirectCast(gvComplexRates.FooterRow.Controls(3),System.Web.UI.WebControls.DataControlFieldCell).Controls(1)
The first of these shows a tag of td. Which makes sense. The second shows text of "10" which is the content for the row above the footer.
Does anybody know why this is happening?
Thanks Dan
Where are you "providing the missing insert ability"?
You have to rebuild the footer-controls on every postback, the GridView.RowCreated-Event would be a good place.
Update:
You have to Databind your GridView after you inserted new rows into your Dropdowns' Tables.
Right, this is a bit embarrassing. I gave a little white lie in the original question. By omission rather than a deliberate attempt to mislead. I am not, in fact, using a GridView but a subclass of it that will display rows when the datasource contains no data. This enables the user to insert new rows when the table is empty. This subclass overrides the FooterRow property and, to my shame, it was this that was getting things wrong. So I made two errors here: first I failed to test my GridView subclass properly and second I sought to prevent what I thought would be unnecessary attention on my subclass by not showing its use in the code snippets I included in the question. My bad. Thanks to Tim for taking the time to try and help me.
Dan

ASP.NET Load & Display DataGrid based on another control, when page loads

On my ASP.NET content page, I have a DropDownList and a DataGrid. The DropDownList is populated from the results of an SQL query when the page loads. I want the DataGrid to be populated from the results of an SQL Query, but that query depends on the selected item of the DropDownList. I have an event handler for DropDownList1.SelectedIndexChanged, which calls a function PopulateDG. This function gets the selected item from the DropDown (defaulting to the first element if SelectedItem is Nothing), creates an SQLDataAdapter, queries the database, fills the DataSet, and finally calls the DataGrid's DataBind(). This all works perfectly when the function is called from the DropDown's event handler.
I would now like to have the DataGrid appear when the page is first loaded, using the information from the first element of the DropDown (since it'd be before the user has selected anything). I have tried putting PopulateDG in the Init, PreInit, PreRender, Load, and Unload handlers for the Page and both controls, to no avail. When I use the debugger, I can see that the ItemsGrid.DataSource does indeed have the information I want, but ItemsGrid.DataBind does not seem to cause the Data Grid to appear on the page like it does when called from the SelectedIndexChanged handler. The control simply doesn't render onto the page.
PopulateDG:
Protected Sub PopulateDG()
Dim WeekId As Integer
Dim DDIdx As Integer
If DropDownList1.SelectedItem Is Nothing Then
DDIdx = 0
Else
DDIdx = DropDownList1.SelectedIndex
End If
WeekId = DropDownList1.Items.Item(DDIdx).Value
Dim myConnection As SqlConnection
Dim SQLCommand As SqlDataAdapter
Dim rootWebConfig As System.Configuration.Configuration
rootWebConfig = Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/Web.config")
Dim connString As System.Configuration.ConnectionStringSettings
connString = rootWebConfig.ConnectionStrings.ConnectionStrings("ConnectionString")
If Not (connString.ConnectionString = Nothing) Then
Console.WriteLine("Northwind connection string = " & connString.ConnectionString)
Else
Console.WriteLine("No Northwind connection string")
End If
myConnection = New SqlConnection(connString.ConnectionString)
SQLCommand = New SqlDataAdapter("SELECT CONVERT(VARCHAR(10), WorkDate, 101) AS WorkDate, CONVERT(VARCHAR(10), WorkStartTime, 8) AS StartTime, CONVERT(VARCHAR(10), WorkEndTime, 8) AS EndTime, BreakMinutes FROM Days WHERE WeekId = " & WeekId & " ORDER BY WorkDate", myConnection)
Dim ds As DataSet = New DataSet()
SQLCommand.Fill(ds)
ItemsGrid.DataSource = ds
ItemsGrid.DataBind() 'DEBUGGER BREAK POINT HERE
End Sub
Content markup of my aspx page:
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" Runat="Server">
<asp:DropDownList ID="DropDownList1"
runat="server"
DataSourceID="TimeSheetDB"
DataTextField="WeekEndLabel"
DataValueField="WeekId"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
AutoPostBack="True">
</asp:DropDownList>
<asp:SqlDataSource ID="TimeSheetDB"
runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [WeekId], 'Week Ending ' + CONVERT(varchar(10), EndDate, 101) AS WeekEndLabel FROM [Weeks] ORDER BY [EndDate]">
</asp:SqlDataSource>
<asp:DataGrid id="ItemsGrid"
BorderColor="black"
BorderWidth="1"
CellPadding="3"
AutoGenerateColumns="true"
runat="server"
>
</asp:DataGrid>
</asp:Content>
At the second to last line of the sub, I have a break point, and using the debugger I can see that ItemsGrid.DataSource.Tables.List(0) is populated exactly as I'd like, but the DataBind function seems to do nothing when called from anywhere except the SelectedItemChanged event handler. How can I make it work correctly when the page first loads?
I figured out the problem. The call to PopulateDG has to come in the DropDown's PreRender event handler. My problem seems to have been that I was trying to use the function either too early (ie, before the items were loaded into the DropDown control) or too late (after ASP had already determined how the DataGrid should appear, I assume, so that calling DataBind at that point had no effect). Clearly, I need to read up more on the various execution phases of pages and controls.

Resources