How to enable and disable buttons in a gridview in asp.net - asp.net

I currently have a GridView with two buttons that I have added using the following code;
<asp:GridView ID="gvResults" AutoGenerateColumns="False" runat="server" Font-Size="small"
DataKeyNames="BeachHutID" OnRowDataBound="gvResults_RowDataBound" CssClass="BBCSearch">
<Columns>
<asp:BoundField DataField="BeachHutID" SortExpression="BeachHutID" Visible="false">
</asp:BoundField>
<asp:ImageField DataImageUrlField="HutImage" ItemStyle-Width="1%" ReadOnly="true" />
<asp:BoundField HeaderText="Facilities" DataField="Facilities" Visible="false"></asp:BoundField>
<asp:BoundField HeaderText="Info" DataField="Info" Visible="false"></asp:BoundField>
<asp:TemplateField>
<ItemTemplate>
<asp:PlaceHolder ID="lblHolder" runat="server"></asp:PlaceHolder>
<br />
<asp:PlaceHolder ID="imgHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>' runat="server"
Text="Hire Beach Hut" OnClick="Hire_Click" />
<asp:Button ID="ButtonLogin" CommandArgument='<%# Eval("BeachHutID") %>' runat="server"
Text="Login to Hire Beach Hut" OnClick="Login_Redirect" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
What I want to happen is if the user is logged in, the btnHire button should be enabled and showing and if they're not logged in, ButtonLoggedIn is showing and btnHire is hidden. This is the code I have at the moment;
Public Sub PopulateGrid()
Dim AvailableHuts As New DataTable
AvailableHuts = GetData()
gvResults.DataSource = AvailableHuts
gvResults.DataBind()
gvResults.Enabled = True
'If statement controlling the enabling and disabling of the Beach Hut booking button
If Session("LoginID") = "" Then
For Each rowItem As GridViewRow In gvResults.Rows
rowItem.Cells(5).Enabled = True
Next
End If
lblCaption.Text = "Your search returned " + CStr(AvailableHuts.Rows.Count) + " results"
End Sub
At the moment both buttons are enabled at all times and I'm not sure what I need to add/changed to get the desired result.
From the answer posted by #Andrei, I have added the following to to this Sub;
Protected Sub gvResults_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles gvResults.RowDataBound
Dim URL(), Text() As String
Dim img As Image
Dim lbl As Label
Dim FacilitiesImg As PlaceHolder = e.Row.FindControl("imgHolder")
Dim Infolbl As PlaceHolder = e.Row.FindControl("lblHolder")
'Added Code from answer
Dim hireBtn As Button = CType(e.Row.FindControl("btnHire"), Button)
hireBtn.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
'Added Code from answer
Dim LoginBtn As Button = CType(e.Row.FindControl("ButtonLogin"), Button)
LoginBtn.Visible = String.IsNullOrEmpty(Session("LoginID"))
If e.Row.RowType = DataControlRowType.DataRow Then
URL = e.Row.DataItem(3).Split(",")
Text = e.Row.DataItem(2).Split(",")
'Add the Facilities Images to the grid Row
For Each item In URL
If item.ToString <> "" Then
img = New Image
img.ImageUrl = item.ToString
FacilitiesImg.Controls.Add(img)
End If
Next
'Add the information to the grid row
'convert # into a carriage return and * into £
For Each item In Text
If item.ToString <> "" Then
lbl = New Label
lbl.Text = Replace(Replace(item.ToString, "#", "<br />"), "*", "£")
Infolbl.Controls.Add(lbl)
End If
Next
End If
End Sub
However I'm receiving the following error when trying to run the program;
Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class
Any assistance would be much appreciated.
Thanks

Not sure how is your authentication implemented, but let's assume you use HttpContext.Current.Request.IsAuthenticated. Then you can just manipulate Visible property of the buttons in code behind:
btnHire.Visible = HttpContext.Current.Request.IsAuthenticated
ButtonLoggedIn.Visible = Not HttpContext.Current.Request.IsAuthenticated
Update.
Sorry, somehow missed from the post the fact that you seems to be using Session("LoginID") to decide if the use is logged in. The you can do this:
btnHire.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
ButtonLoggedIn.Visible = String.IsNullOrEmpty(Session("LoginID"))
Update 2.
As it turns out, buttons are a part of GridView row. As they are inside the template, you cannot really reach them in the code behind. So you can take two options.
First, you can subscribe to RowDataBound event (which you already did), and inside it do FindControl in the current row to find the necessary button:
Sub gvResults_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
...
Button hireBtn = CType(e.Row.FindControl("btnHire"), Button);
hireBtn.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
and likewise for the second button.
Second, you can try doing it in the markup:
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>'
runat="server" Text="Hire Beach Hut" OnClick="Hire_Click"
Visible=<%# String.IsNullOrEmpty(Session("LoginID")) %> />

try
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>' runat="server" Visible='<%# islogin()?true:false %>' Text="Hire Beach Hut" OnClick="Hire_Click" />
<asp:Button ID="ButtonLoggedIn" CommandArgument='<%# Eval("BeachHutID") %>' runat="server" Visible='<%# islogin()?false:true %>' Text="Login to Hire Beach Hut" OnClick="Login_Redirect" />
paste this code to aspx.cs page:
Public Shared Function isLogin() As Boolean
Dim stat As Boolean = False
Try
If Session("LoginID") IsNot Nothing AndAlso Session("LoginID") <> "" Then
stat = True
End If
Catch e1 As Exception
stat = False
End Try
Return stat
End Function
Edit2:
Visible='<%# islogin()?false:true %> this means if isLogin() return true then Visible property set to false else it's visible property set to true.

Related

Explicit iteration in Gridview and using findControl returns Nothing

I am trying to loop through GridView control. It contains radio button and I would like to set it's checked property based on certain condition. However, the findControl method returns nothing.
Here is the aspx code:
<asp:GridView ID="GridViewInfo"
runat="server"
AutoGenerateColumns="False"
DataKeyNames="Result_ID">
<Columns>
<asp:TemplateField HeaderStyle-Width="3%" HeaderText="SELECT">
<ItemTemplate>
<input name="RadioButtonResultID"
id="RadioButtonResultID" type="radio"
value='<%# Eval("Result_ID") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Characteristics"
DataField="Characteristics" />
</Columns>
</asp:GridView>
Code behind:
Private Sub HighlightSelectedRow(ByVal id As String)
Dim rowCount As Int32 = 0
For Each row As GridViewRow In GridViewLabInfo.Rows
If (GridViewLabInfo.DataKeys(rowCount).Value.ToString() = id) Then
row.CssClass = "SelectedRowStyle"
'Both of the below lines are failing
TryCast(row.FindControl("RadioButtonResultID"), RadioButton).Checked = True
CType(row.FindControl("RadioButtonResultID"), RadioButton).Checked = True
End If
rowCount = rowCount + 1
Next
End Sub
You cast is wrong. That is not a asp.net radio button (RadioButton), but is a HTML one,
So your cast in in this case should be:
TryCast(row.FindControl("RadioButtonResultID"), HtmlInputRadioButton ).Checked = True
And you don't even need the cast, but this should work:
Dim MyRadioBut As HtmlInputRadioButton = row.FindControl("RadioButtonResultID")
MyRadioBut.Checked = True
However, in BOTH of the above cases? You can't pick up the control in code behind unless you state that control is rendered by the server.
You need to add the runat="server".
eg this:
<input name="RadioButtonResultID"
id="RadioButtonResultID" type="radio"
value='<%# Eval("Result_ID") %>' runat="server" />

Dynamic file download buttons in VB .NET

I have a page in a VB NET 2005 web project. On page load, it takes data from the logged in user, looks up a set of documents owned by that user, and creates a "download" button for each. Currently, this button opens a new window that streams the document, but we'd like the button itself to trigger a download.
I've got some options for this, but they all seem kind of hacky, and while I haven't found any good solutions, this seems like it should be a solved problem.
The buttons are in a form (so postback with hidden fields is one of the "hacky" options).
Let's say I have a GridView with 3 columns: Filename, Size and a Download button. Then set the CommandName and CommandArgument of the button. For security reason, it might be a better idea to use the user's document id instead of the full path name like I did. You can get the real file using combination of current user and the document id.
<asp:TemplateField HeaderText="Filename">
<ItemTemplate>
<asp:Label ID="lblFilename" runat="server" Text='<%# Bind("Filename") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Size">
<ItemTemplate>
<asp:Label ID="lblSize" runat="server" Text='<%# Bind("Size") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Download">
<ItemTemplate>
<asp:Button ID="btnDownload" runat="server" Text="Download"
CommandName="Download" CommandArgument='<%# Eval("FullName") %>' />
</ItemTemplate>
</asp:TemplateField>
This is the class which I use to hold the list of files for download. A list of this class binds to the GridView.
Public Class MyFileInfo
Public Property Filename As String
Public Property Fullname As String
Public Property Size As Long
End Class
Last is handling the Download button click. I use the CommandName and CommandArgument to pass what button is click and what file it needs to give to the browser. I use stream and write to the browser with proper MIME type in the header.
Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
If e.CommandName = "Download" Then
DownloadFile(e.CommandArgument)
End If
End Sub
Sub DownloadFile(filename As String)
Using fs = New FileStream(filename, FileMode.Open)
Response.BufferOutput = False
Response.AddHeader("Content-Length", fs.Length.ToString())
Response.AppendHeader("Content-Disposition", "attachment;filename=" & Path.GetFileName(filename))
Response.ContentType = "application/msword"
fs.Position = 0
fs.CopyTo(Response.OutputStream)
Response.Flush()
Response.End()
End Using
End Sub
Full code (aspx):
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="Filename">
<ItemTemplate>
<asp:Label ID="lblFilename" runat="server" Text='<%# Bind("Filename") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Size">
<ItemTemplate>
<asp:Label ID="lblSize" runat="server" Text='<%# Bind("Size") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Download">
<ItemTemplate>
<asp:Button ID="btnDownload" runat="server" Text="Download"
CommandName="Download" CommandArgument='<%# Eval("FullName") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
Full code (code behind):
Imports System.IO
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then BindGridList()
End Sub
Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
If e.CommandName = "Download" Then
DownloadFile(e.CommandArgument)
End If
End Sub
Sub BindGridList()
GridView1.DataSource = GetFiles()
GridView1.DataBind()
End Sub
Function GetFiles() As List(Of MyFileInfo)
Dim listFileInfos = New List(Of MyFileInfo)
Dim dirInfo = New DirectoryInfo(Server.MapPath("~/Data"))
Dim fileInfos = dirInfo.GetFiles("*.doc")
For Each fileInfo In fileInfos
listFileInfos.Add(New MyFileInfo With {.Filename = fileInfo.Name, .Size = fileInfo.Length, .Fullname = fileInfo.FullName})
Next
Return listFileInfos
End Function
Sub DownloadFile(filename As String)
Using fs = New FileStream(filename, FileMode.Open)
Response.BufferOutput = False
Response.AddHeader("Content-Length", fs.Length.ToString())
Response.AppendHeader("Content-Disposition", "attachment;filename=" & Path.GetFileName(filename))
Response.ContentType = "application/msword"
fs.Position = 0
fs.CopyTo(Response.OutputStream)
Response.Flush()
Response.End()
End Using
End Sub
End Class
Public Class MyFileInfo
Public Property Filename As String
Public Property Fullname As String
Public Property Size As Long
End Class

Trying to disable edit button based on gridview result - Object reference not set to an instance of an object - vb.net

I have a gridview that I need to disable the "Edit" linkbutton when it's not the current week. I have accomplished this in my code, but when I got that to work, it took away the update and cancel functionality, giving me a Object reference not set to an instance of an object error when i press update or cancel. I'll post the entire code, but I want to point out this is the code that makes the disabling work and the code that I can comment out and get the update and cancel functions to work again:
'Disable edit button if not the current week
For i As Integer = 0 To GridView1.Rows.Count - 1
Dim lbl As Label
lbl = CType(GridView1.Rows(i).FindControl("lblWeekStart"), Label)
If lbl.Text <> currentDay Then
GridView1.Rows(i).Cells(0).Enabled = False
End If
Next
More specifically, it errors out on this line b/c of lbl.Text:
If lbl.Text <> currentDay Then
But here's the entire sub routine:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Get User's Name
Dim lblFtrSubmitter As Label = GridView1.FooterRow.FindControl("lblFtrSubmitter")
lblFtrSubmitter.Text = Context.User.Identity.Name
'Get Time Recorded
Dim lblFtrTimeRecorded As Label = GridView1.FooterRow.FindControl("lblFtrTimeRecorded")
lblFtrTimeRecorded.Text = Date.Now
'Get The Sunday of Current Week and put into label
Dim lblFtrWeekStart As Label = GridView1.FooterRow.FindControl("lblFtrWeekStart")
Dim myDate As Date = DateTime.Today
Dim dayDiff As Integer = myDate.DayOfWeek - DayOfWeek.Sunday
Dim currentDay As Date = myDate.AddDays(-dayDiff) 'Sunday
For i = 1 To 7
Console.WriteLine(currentDay)
'Do something with current day
currentDay = myDate.AddDays(-myDate.DayOfWeek)
lblFtrWeekStart.Text = currentDay
Next
'Disable edit button if not the current week
For i As Integer = 0 To GridView1.Rows.Count - 1
Dim lbl As Label
lbl = CType(GridView1.Rows(i).FindControl("lblWeekStart"), Label)
If lbl.Text <> currentDay Then
GridView1.Rows(i).Cells(0).Enabled = False
End If
Next
End If
End Sub
Here's the .aspx code for the template field that contains the linkbuttons:
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="lnkUpdate" runat="server" CausesValidation="True" CommandName="Update"
Text="Update" ></asp:LinkButton>
<asp:LinkButton ID="lnkCancel" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel" ></asp:LinkButton>
</EditItemTemplate>
<FooterTemplate>
<asp:Button ID="btnAdd" runat="server" Text="ADD" CommandName="Insert" OnClientClick="return confirm('Are you sure you want to add this record?');" />
</FooterTemplate>
<ItemTemplate>
<asp:LinkButton ID="lnkEdit" runat="server" CausesValidation="False" CommandName="Edit"
Text="Edit" ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Any help is greatly appreciated!
The problem here is this line is returning Nothing
lbl = CType(GridView1.Rows(i).FindControl("lblWeekStart"), Label)
Hence the following line will thrown an exception because lbl = Nothing
If lbl.Text <> currentDay Then
Looking at the template code it appears there is nothing named "lblWeekStart" available to find. This means FindControl is return Nothing as expected. You need to switch the code to look for the correct ID or change the place where you are searching for "lblWeekStart"

Object reference not set to an instance of an object. - Visual Basic (Web)

So, I'm having a slight problem with my code.
I was working on a small school project (recreation of book library) and encountered a problem which I cannot get a grasp of.
So, the user can search for a list of books, and after the list is populated (via DataList control), a small button "Book now" (Reserve) appears which user can click and reserve his book.
This is the code for the DataList control that resides in "Search.aspx"
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId" DataSourceID="SearchSqlDataSource" CssClass="searchControl">
<ItemTemplate>
<div class="pictureOfFoundBook">
<asp:Image ID="pictureOfFoundBook_imageLink" runat="server" ImageUrl='<%#"~/GetImage.aspx?knjigaId=" & Eval("knjigaId") & "&img=naslovnica" %>' />
</div>
<div class="descriptionOfFoundBook">
Naziv: <asp:Label ID="Label1" runat="server" Text='<%# Eval("naziv") %>' /><br />
Godina izdanja: <asp:Label ID="Label2" runat="server" Text='<%# Eval("godinaIzdanja") %>' /><br />
Broj stranica : <asp:Label ID="brojStranicaLabel" runat="server" Text='<%# Eval("brojStranica") %>' /><br />
Izdavač: <asp:Label ID="NazivIzdavacaLabel" runat="server" Text='<%# Eval("NazivIzdavaca") %>' /><br />
Vrsta tiskovine : <asp:Label ID="NazivVrsteTiskovineLabel" runat="server" Text='<%# Eval("NazivVrsteTiskovine") %>' /><br />
Kategorija: <asp:Label ID="NazivKategorijeLabel" runat="server" Text='<%# Eval("NazivKategorije") %>' /><br /><br />
<asp:HyperLink ID="foundBookEditHL_adminOnly" runat="server" NavigateUrl='<%# "~/admin/knjigeEdit.aspx?knjigaId=" & Eval("knjigaId") %>'>Uredi knjigu</asp:HyperLink><br />
<asp:Button ID="rezervacijeButton" runat="server" Text="Rezerviraj" OnClick="rezervacijaClick" CommandArgument='<%# Eval("knjigaId") %>'/><br />
<asp:Label ID="rezStatusLabel" runat="server"></asp:Label>
<asp:PlaceHolder ID="rezStatusPlaceholder" runat="server"></asp:PlaceHolder>
</div>
<hr />
</ItemTemplate>
</asp:DataList>
I've set the DataList1 control as a Friend sub so I can access the controls in it from another sub;
Friend Sub DataList1_ItemCreated(sender As Object, e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemCreated
End Sub
I was trying to do the following; on the click of a button "rezervacijeButton", a function "rezervacijaClick" runs, which populates the table in the database.
Protected Sub rezervacijaClick(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = DataList1.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = sender
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
'Try
' rezstatus.Text = "testing..."
'Catch ex As Exception
' exlabel.Text = "POGREŠKA"
' exlabel.ForeColor = Drawing.Color.Red
'End
End Sub
The next thing I wanted to do in the function "rezervacijaClick" was to set the text value of the Label (with ID "rezStatusLabel", which resides inside the DataList1 control) to "SOME TEXT" after the "Reserve" button is clicked.
But after the button click, I get the following error :
Object reference not set to an instance of an object.
Line 21:
Line 22: buttonsender.Visible = False
Line 23: rezstatus.Text = "aaa"
Line 24:
Line 25: 'Try
Your rezstatus object is Nothing (null).
This is happening because you aren't looking in the right place for your label.
Each record of data you bind to the DataList will create a new hierarchy of controls, containers that hold the other controls you have defined in your ItemTemplate.
The immediate descendants of DataList1 will be a collection of DataListItem objects and then you will have your controls inside those.
Since we don't know for sure (unless you know you are only binding one record to the DataList) which DataListItem the desired label will be in, we simply walk backwards up the control tree and find the label from there.
Because you are responding to a button click event in your rezervacijaClick method, the parameter sender will be of type Button and will come from rezervacijeButton, so we can use that information to find your label:
Dim clickedButton As Button = CType(sender, Button) 'convert the sender parameter to the correct type: Button
Dim buttonParent As Control = clickedButton.Parent 'get a reference to the button's parent control
Dim rezstatus As Label = CType(buttonParent.FindControl(""), Label) 'find the label by ID and convert it to a Label as the return type of FindControl is Control
I would recommend that, instead of using the Button click event, you use the DataList.ItemCommand event. It will make your life a lot easier. This event fires whenever a Button is clicked within a row of your DataList control.
This way, you get the index passed in through the DataListCommandEventArgs parameter. then you would just need to update your DataList markup to add the event handler:
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId"
DataSourceID="SearchSqlDataSource" CssClass="searchControl"
ItemCommand="DataList1_ItemCommand" >
And your handler code would look like this:
Protected Sub DataList1_ItemCommand(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = e.Item.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = e.Item.FindControl("rezervacijeButton")
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
End Sub

ASP GridView Refresh after Excel Export not working

I have a Gridview inside an Ajax UpdatePanel. Inside each GV row I have a checkbox field. The idea is that the user checks the lines they want, and click a button to both update a label in that row as "shipped" and then also export the checked lines to an xls file (csv really).
When my codebehind fires it loops through the gridview rows, looks for the checks, updates the database to mark each line and then I use .DataBind() to refresh the grid. This works perfectly and as expected.
Now I want to also export the checked rows to excel. So I created a method for doing this and popped it in after updating each row for marking the lines and BEFORE the .DataBind() refresh. Now the .DataBind() never fires to refresh. I do receive the XLS download and if I manually refresh the screen, the lines are updated as expected.
Here's my code:
ASPX (Just a portion of the gridview):
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AllowSorting="True" AutoGenerateColumns="False"
DataKeyNames="MinqNum" DataSourceID="SqlDataSource1" Font-Size="Small" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1px" CellPadding="0">
<RowStyle Font-Size="Small" HorizontalAlign="Left" VerticalAlign="Bottom" BorderColor="#999999"
BorderStyle="Solid" BorderWidth="1px" Wrap="true" />
<Columns>
<asp:TemplateField>
<ItemStyle CssClass="ItemStyle"/>
<HeaderStyle Wrap="true" Font-Size="X-Small" HorizontalAlign="Center"
VerticalAlign="Bottom" BorderWidth="0px" />
<ItemTemplate>
<asp:ImageButton ID="btn_editss" runat="server" CommandName="Edit" ImageUrl="~/images/edit.gif" />
</ItemTemplate>
<EditItemTemplate>
<asp:ImageButton ID="btn_savess" runat="server" CommandName="Update" ImageUrl="~/images/save.gif" />
<asp:ImageButton ID="btn_cancelss" runat="server" CommandName="Cancel" ImageUrl="~/images/cancel.gif" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Date" SortExpression="MinqDate">
<ItemStyle CssClass="ItemStyle" HorizontalAlign="Center" Font-Size="Smaller"/>
<HeaderStyle Wrap="true" Font-Size="X-Small" HorizontalAlign="Center" VerticalAlign="Bottom" BorderWidth="0px"/>
<ItemTemplate>
<asp:Label ID="lbl_minqdate" runat="server" Text='<%#Bind("MinqDate", "{0:MM/dd/yy}") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:Label ID="lbl_minqdate" runat="server" Text='<%#Bind("MinqDate", "{0:MM/dd/yy}") %>'></asp:Label>
</EditItemTemplate>
</asp:TemplateField>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
Button Click Event (codebehind):
Protected Sub btn_markshipped_clicked(ByVal sender As Object, ByVal e As EventArgs)
For Each row As GridViewRow In GridView1.Rows
If row.RowType = DataControlRowType.DataRow Then
Dim isChecked As Boolean = DirectCast(row.FindControl("cb_supship"), CheckBox).Checked
If isChecked Then
'btn_markshipped.Text = "changed"
Dim cmd As New SqlCommand("UPDATE InquiryV4.dbo.Main SET Sup_Shipped = 'S' WHERE MinqNum = #MinqNum")
cmd.Parameters.AddWithValue("#MinqNum", row.Cells(5).Controls.OfType(Of Label)().FirstOrDefault().Text)
'cmd.Parameters.AddWithValue("#Country", row.Cells(2).Controls.OfType(Of DropDownList)().FirstOrDefault().SelectedItem.Value)
'cmd.Parameters.AddWithValue("#CustomerId", gvCustomers.DataKeys(row.RowIndex).Value)
Me.ExecuteQuery(cmd, "UPDATE")
End If
End If
Next
'btnUpdate.Visible = False
'Me.BindGrid()
btn_exportexcel()
GridView1.DataBind()
End Sub
btn_exportexcel sub (codebehind):
Private Sub btn_exportexcel()
Dim dt = New DataTable()
dt.Columns.Add("MTX PN")
dt.Columns.Add("Inq#")
dt.Columns.Add("Customer")
dt.Columns.Add("Qty")
dt.Columns.Add("Eng")
dt.Columns.Add("A/M")
For Each gvrow As GridViewRow In GridView1.Rows
Dim chk As Boolean = DirectCast(gvrow.FindControl("cb_supship"), CheckBox).Checked
If chk = True Then
Dim i = gvrow.RowIndex
Dim lbl_mtxpn As Label = gvrow.FindControl("lbl_mtxpn")
Dim lbl_inqnum As Label = gvrow.FindControl("lbl_inqnum")
Dim lbl_customer As Label = gvrow.FindControl("lbl_customer")
Dim lbl_SamplesRequested As Label = gvrow.FindControl("lbl_SamplesRequested")
Dim lbl_AssignedTo As Label = gvrow.FindControl("lbl_AssignedTo")
Dim lbl_LTN_Eng As Label = gvrow.FindControl("lbl_LTN_Eng")
Dim lbl_AcctMGR As Label = gvrow.FindControl("lbl_AcctMGR")
Dim dr = dt.NewRow()
dr.Item("MTX PN") = Convert.ToString(lbl_mtxpn.Text)
dr.Item("Inq#") = Convert.ToString(lbl_inqnum.Text)
dr.Item("Customer") = Convert.ToString(lbl_customer.Text)
dr.Item("Qty") = Convert.ToString(lbl_SamplesRequested.Text)
dr.Item("Eng") = Convert.ToString(lbl_LTN_Eng.Text) + "(" + Convert.ToString(lbl_AssignedTo.Text) + ")"
dr.Item("A/M") = Convert.ToString(lbl_AcctMGR.Text)
dt.Rows.Add(dr)
End If
Next
Dim GridView2 = New GridView()
GridView2.DataSource = dt
GridView2.DataBind()
Response.Clear()
Response.Buffer = True
Response.ContentType = "application/ms-excel"
Response.AddHeader("content-disposition", String.Format("attachment;filename={0}.xls", "selectedrows"))
Response.Charset = ""
Dim sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
GridView2.RenderControl(hw)
Response.Output.Write(sw.ToString())
Response.End()
End Sub
As I said, without the export function the gridview.databind() works as expected and updates the gridview. As soon as the export function is put inbetween, it blocks the .databind() from happening.
Any ideas? Just for giggles I also tried a response.redirect instead and that has the same issue.
This is happening because you are:
Clearing the response;
Sending the Excel file;
Ending the response.
In other words, the server's reply to your request is to send the excel file. It doesn't send a new batch of HTML to the browser, because you told it to stop after the file was sent. As you have observed, your page doesn't change, because you didn't send your browser any new HTML.
I don't believe it's possible to both send a file AND send new HTML to the browser, but I'm open to being proved wrong. Most cases I've seen of people attempting both these things involve a rebind and page refresh first, and then an Ajax-like GET call to the server to get the Excel file. Other options include opening a new, very small window that just does a GET and returns the Excel file, and then closes after it's sent.
Are you trying to have 2 GridViews or two views of the same data displayed in the same GridView?

Resources