Updating af GridView - maybe a viewstate issue - asp.net

I am trying to update GridView with a lot of records through an ObjectDataSource. I am only updating the changed records, so I use ViewState to check if the original datatable has changed. It works fine on my localhost/IIS but when I try the same solution on the deployment server it gives me an error:
Index was outside the bounds of the array.
In this line of code:
Dim row As System.Data.DataRow = originalDataTable.Select(String.Format("ID = '{0}'", currentID))(0)
Below is an example of my code. Is there a problem with ViewState on the server?
Private ProdNum As String
Private tableCopied As Boolean = False
Private originalDataTable As System.Data.DataTable
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
If Not tableCopied Then
originalDataTable = CType(e.Row.DataItem, System.Data.DataRowView).Row.Table.Copy()
ViewState("originalValuesDataTable") = originalDataTable
tableCopied = True
End If
End If
End Sub
Protected Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click, btnUpdate1.Click
originalDataTable = CType(ViewState("originalValuesDataTable"), System.Data.DataTable)
For Each r As GridViewRow In GridView1.Rows
If IsRowModified(r) Then GridView1.UpdateRow(r.RowIndex, False)
Next
' Rebind the Grid to repopulate the original values table.
tableCopied = False
GridView1.DataBind()
End Sub
Protected Function IsRowModified(ByVal r As GridViewRow) As Boolean
Dim currentID As Guid
Dim currentNyhed as Boolean
currentID = Guid.Parse(GridView1.DataKeys(r.RowIndex).Value.ToString())
currentNyhed = CType(r.FindControl("CheckBoxNews"), CheckBox).Checked
Dim row As System.Data.DataRow = originalDataTable.Select(String.Format("ID = '{0}'", currentID))(0)
If Not currentNyhed.Equals(row("News").ToString()) Then Return True
Return False
End Function
The GridView is bound to an ObjectDataSource with these basic settings:
<asp:ObjectDataSource ID="ObjectDataSource1" ViewStateMode="Enabled" EnableViewState="true" runat="server" InsertMethod="Insert" OldValuesParameterFormatString="original_{0}" SelectMethod="GetDataByOverruled" TypeName="DSoverskrivslisteTableAdapters.Shop_Products_Egenskaber_OverrulingTableAdapter" UpdateMethod="Update">
The whole thing is based on this tutorial below. Instead of SqlDataSource I am using the ObjectDataSource which - as mentioned - works fine when run on my localhost, but gives me the error when uploaded to the deployment server.
http://msdn.microsoft.com/en-us/library/aa992036(v=vs.90).aspx
Please help.

Related

Unable to cast object of type 'System.String' to type 'System.Web.UI.WebControls.GridViewRow'

I need your help on this. I am not sure why I am getting this error. Here is what I am trying to do. I am populating a button into the GridView based on the data from database however I have no issue with that. But the issue comes when I am trying to do RowCommand. I am trying to get the individual id from each row so that i can use for my sql query
Protected Sub GridView2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound
Dim row As GridViewRow = e.Row
If row.RowType = DataControlRowType.DataRow Then
Dim lb2 As New LinkButton
lb2.ID = "lbCancel"
lb2.Text = "Cancel"
lb2.CommandName = "CancelRow"
lb2.CommandArgument = "'<%#Eval('tripID')%>"
row.Cells(10).Controls.Add(lb2)
If row.Cells(8).Text = "Driver" Then
Dim lb As New LinkButton()
lb.ID = "lbEnd"
lb.Text = "End"
lb.CommandName = "EndRow"
row.Cells(9).Controls.Add(lb)
End If
End If
End Sub
Protected Sub GridView2_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView2.RowCommand
If (e.CommandName = "CancelRow") Then
Dim row As GridViewRow = e.CommandArgument
Dim index As String = Convert.ToString(DataBinder.Eval(row.DataItem, "tripID"))
ElseIf (e.CommandName = "EndRow") Then
End If
End Sub
I suspect the issue to be cause by Dim index As String = Convert.ToString(DataBinder.Eval(row.DataItem, "tripID")) however i have no idea how to solve it.
Hope you guys can help. Thanks!
If you try to debug the code, you will get that you are getting
Unable to cast object of type 'System.String' to type 'System.Web.UI.WebControls.GridViewRow'
error at line
Dim row As GridViewRow = e.CommandArgument
Here you are trying to convert String into WebControls GridViewRow. In this case you should try
Dim row As GridViewRow = DirectCast(DirectCast(e.CommandSource, LinkButton).NamingContainer, GridViewRow)
This will give you a GridViewRow and will evaluate value you are passing as CommandArgument.

ASP VB Stuck on Dynamic Controls, Viewstate, and Postback. Could really use some help to get back on track

I've been reading posts and articles and just getting a little confused and consequently burning through time I don't have at the moment
Can someone look at my code and tell me where I've gone wrong?
Partial Class PayerContacts
Inherits System.Web.UI.Page
Dim connStrDRContacts As String = ConfigurationManager.ConnectionStrings("DRContacts_SQL").ConnectionString
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
navBuild()
End Sub
Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
If IsPostBack Then
LoadContacts(ViewState("objSender"))
End If
End Sub
Private Function navBuild() As Integer
Dim SQLstrDRs As String = "SELECT * FROM DRList"
Dim DbConnDRs As SqlConnection = New SqlConnection(connStrDRContacts)
DbConnDRs.Open()
Dim dtDRsTemp As New DataTable
Dim SQLAdapterDRs As New SqlDataAdapter(SQLstrDRs, DbConnDRs)
SQLAdapterDRs.Fill(dtDRsTemp)
'Loop through each row of the DataView to create HTML table data
Dim NewTableRow As New TableRow
For Each row As DataRow In dtDRsTemp.Rows
'CREATE table with button to display contacts related to client (one to many)
Dim NewTableButton As LinkButton = New LinkButton
NewTableButton.ID = "btnDRName" & NewTableText
NewTableButton.ViewStateMode = UI.ViewStateMode.Enabled
AddHandler NewTableButton.Click, AddressOf LoadContacts
Next
Return 0
End Function
Protected Sub LoadContacts(sender As Object, e As EventArgs)
Dim LoopCount As Integer = 0
Dim SQLstrLoadTable As String = "SELECT * FROM ContactList WHERE DRVendor = '" & sender.Text.ToString & "'"
and so on....
SQLAdapterLoadTable.Fill(dtLoadTableTemp)
Dim NewTableRow As New TableRow
For Each row As DataRow In dtLoadTableTemp.Rows
'CREATE Accordion to display data
NewAccordion.ID = "ContactAccordion" & LoopCount
NewAccordion.Visible = True
blah, blah...
'SET Pane
NewAccordionPane.HeaderContainer.ID = "PaneHeader" & LoopCount
NewAccordionPane.ContentContainer.ID = "PaneContent" & LoopCount
'CREATE button to open ModalPopup to EDIT each record
Dim imgGear As New ImageButton
imgGear.ID = "btnGear" & row!ID.ToString
imgGear.ViewStateMode = UI.ViewStateMode.Enabled
AddHandler imgGear.Click, AddressOf EditRecord
'LOAD Pane
NewAccordionPane.HeaderContainer.Controls.Add(NewHeaderTable)
NewAccordionPane.ContentContainer.Controls.Add(New LiteralControl(NewTableText))
ViewState("objSender") = sender
End Sub
Protected Sub EditRecord(ByVal sender As Object, ByVal e As EventArgs)
'Open ModalPopup to edit record
popup.Show()
pnlAddEdit.Visible = True
End Sub
End Class
The Infinities Loop articles on ViewState and Dynamic Controls should really be read by every Webforms developer: -
http://mocha.mojoskins.com/SharedFiles/Download.aspx?pageid=566&mid=786&fileid=38
http://weblogs.asp.net/infinitiesloop/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_
The examples are in C# but you should be able to figure out what's going on, it's the same base class library after all.

How to keep DataTable persistent?

I have a Gridview filled by a dataTable, filled by a DataAdapter. That's how grid is initially loaded in Page_Load.
To add a search funcionality, I make the same but passing TextBox.Text as parameter to the SELECT... LIKE ... statement.
To add an edit funcionality(a button in every row) I need the previous data in the dataTable, and if I performed a search before editing I need only the result of the search in my dataTable.
The problem is, I don't know how to keep its value alive (persistent), and dataTable has 0 columns when I press teh edit button, so it doesn't display anything to edit.
I guess it happens because I'm using Using, and dataTable is probably getting cleaned after End Using.
In that case, whta can I do to fix it? I thought removing miconn.Close() but it doesn't solve anything, in fact, I don't know if connection is still open after End Using.
Code:
Dim con As New Connection
Dim table As New DataTable()
Private Sub fill_grid()
Using miconn As New SqlConnection(con.GetConnectionString())
Dim sql As String = "SELECT area,lider_usuario FROM AREA"
Using command As New SqlCommand(sql, miconn)
Using ad As New SqlDataAdapter(command)
ad.Fill(table)
GridView1.DataSource = table
GridView1.DataBind()
'miconn.Close()
End Using
End Using
End Using
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
fill_grid()
End If
End Sub
Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSearch.Click
Dim miCon As New Connection
Using miconn As New SqlConnection(miCon.GetConnectionString())
Dim sql As String = "SELECT area,lider_usuario FROM AREA WHERE area LIKE #area"
Using command As New SqlCommand(sql, miconn)
command.Parameters.Clear()
command.Parameters.Add("#area", SqlDbType.VarChar).Value = "%" + TextBox1.Text + "%"
Using ad As New SqlDataAdapter(command)
ad.Fill(table)
GridView1.DataSource = table
GridView1.DataBind()
'miconn.Close()
End Using
End Using
End Using
End Sub
Protected Sub EditRow(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
GridView1.DataSource = table
GridView1.DataBind()
End Sub
Protected Sub CancelEditRow(ByVal sender As Object, ByVal e As GridViewCancelEditEventArgs)
GridView1.EditIndex = -1
GridView1.DataSource = table
GridView1.DataBind()
End Sub
BindGrid()
{
var dt = YourMethodReturningDatatable();
ViewState["Table"] = dt;
grid.DataSource = ViewState["Table"];
grid.Databind();
}
page_load
{
if(not ispostback) // not because my 1 key stopped working.
{
BindGrid();
}
}
I would suggest you to make two different functions for filling the data table and binding it. Call the filling function before the !IsPostBack condition and do the binding inside the condition. Here is the sample code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim table as new DataTable
table = GetData() 'The function that would return a data table
If Not IsPostBack Then
GridView1.DataSource = table
GridView1.DataBind()
End If
End Sub
Private Function GetData() As DataTable
Using miconn As New SqlConnection(con.GetConnectionString())
Dim sql As String = "SELECT area,lider_usuario FROM AREA"
Using command As New SqlCommand(sql, miconn)
Using ad As New SqlDataAdapter(command)
ad.Fill(table)
GetData = table
miconn.Close()
End Using
End Using
End Using
End function
Hope it helps.

setting radiobuttonlist value within a gridview using code behind

I am trying to set the selected value of a radiobuttonlist that is a template column within a gridview. I am having to do this using the code behind as the database field containing the data (Status) contains null values hence I cant used SelectedValue='<%# Bind("Status") %>' on the asp side.
It has been suggested that I use onRowDataBound to do this and use DataItem to retrieve the value from the datasource and used it to set the radiobuttonlist selected value but I'm not sure how to do this in vb code.
I've tried the following:
Protected Sub gv_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim radioList = TryCast(e.Row.FindControl("rblActions"), RadioButtonList)
' this will be the object that you are binding to the grid
Dim myObject = TryCast(e.Row.DataItem, DataRowView)
Dim sStatus As String = Convert.ToString(myObject("Status"))
If sStatus <> Nothing Then
radioList.SelectedValue = sStatus
End If
End If
End Sub
but it hasnt work. Any help would be appreciated. Thanks
Found my own solution as follows:
Sub gv_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim rbl As RadioButtonList = CType(e.Row.FindControl("rblActions"), RadioButtonList)
Dim selected As String = e.Row.DataItem("Status").ToString
If Not IsNothing(selected) Then
rbl.SelectedValue = selected
End If
End If
End Sub

how to highlight the biggest value in a Gridview

I have a gridview that is binded.
And i want to change the color of the font for the longest leadtime even if there are duplicates. I have no idea on how to write my if statement.
This is a rough idea of what i want to do, though I know this code is wrong.
if Max(LeadTime) Then
GridView.ForeColor = Color.Red
Can anyone help me?
You first need to get the max value from your datasource. You can do this with linq:
maxLeadTime = ds.Max(dsi => dsi.LeadTime)
In your item data bound event handler, compare the bound item with the max value:
if (item.LeadTime == maxLeadTime)
{
/* do stuff */
}
(VB.NET version) Assuming you are binding you Grid to a datatable, this is how you will do it.
Private maxVal As Decimal
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.Page.IsPostBack Then
dim dt as datatable = GetTable()
maxVal = ds.AsEnumerable.Max(Function(dr) dr("lead_time"))
gv.DataSource = dt
gv.DataBind()
End If
End Sub
Private Sub gv_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gv.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim dr As DataRowView = e.Row.DataItem
If dr("lead_time") = maxVal Then
e.Row.BackColor = Drawing.Color.Red
End If
End If
End Sub
it would be the same if you are binding it to a list(of T)
In PAge Load:
maxVal = urList.Max(Function(x) x.LeadTime)
In Row dataBound:
Dim uc As urClass = e.Row.DataItem
If uc.LeadTime = maxVal Then
e.Row.BackColor = Drawing.Color.Red
End If

Resources