Editable gridview - what are the basics? - asp.net

I'm trying to create a simple example of an editable gridview, and for some reason can't seem to get the basics working. Why is this example not displaying the label Bar and a textbox when I click on "edit"?
aspx:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="gv.aspx.vb" Inherits="WebRoot.gv" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="gv" runat="server" AutoGenerateEditButton="true" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Foo">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text="Foo" />
<asp:Label ID="lblQuarter" runat="server" Text='<%# Eval("fooVal") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:Label ID="lblQuarter" runat="server" Text='Bar' />
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Eval("fooVal") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
code behind:
Public Class MyFoo
Public ReadOnly Property FooVal() As String
Get
Return _val
End Get
End Property
Private _val As String = String.Empty
Public Sub New(ByVal val As String)
_val = val
End Sub
End Class
Partial Public Class gv
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim l As New List(Of MyFoo)
l.Add(New MyFoo("first"))
l.Add(New MyFoo("second"))
gv.DataSource = l
gv.DataBind()
End Sub
Private Sub gv_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles gv.RowEditing
Dim x As String
x = "foo"
End Sub
End Class

Try hooking up OnRowEditing to your gv_RowEditing method. I'm surprised you don't get an error page, something like "fired event RowEditing which wasn't handled".
<asp:GridView ID="gv" OnRowEditing="gv_RowEditing" ...
Update
My bad. I assumed c# and keep forgetting to check the language. Put this in your rowediting method and the edit will work. But there's more to do in the cancel and update events.
gv.EditIndex = e.NewEditIndex
Dim l As New List(Of MyFoo)
l.Add(New MyFoo("first"))
l.Add(New MyFoo("second"))
gv.DataSource = l
gv.DataBind()
More details here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowediting.aspx

Related

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

Assigning FormView value to VB variable

I am trying to assign a FormView value to a VB variable.
I am using code that works fine when first_nameTextBox is a TextBox and user enters data directly, but fails when first_nameTextBox is a label populated from a database via FormView.
Error I receive is BC30451: 'FormView2_first_nameTextBox' is not declared. It may be inaccessible due to its protection level.
Any help much appreciated.
The code is below;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# Page Language="VB" %>
<%# Import Namespace="System.Net.Mail" %>
<%# Import Namespace="System.Text" %>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr">
<head runat="server">
<!-- Scripting area here -->
<script runat="server" type="text/vbscript">
Protected Sub btnSubmit_click (ByVal sender As Object, ByVal e As EventArgs)
If IsPostBack Then
Dim sc As SmtpClient = New SmtpClient("relay.hostinguk.net")
Dim sb As StringBuilder = New StringBuilder()
Dim msg As MailMessage = Nothing
sb.Append("Name : " + FormView2_first_nameTextBox.Text + vbCrLf)
Try
msg = New MailMessage("from#company.com", _
"to#company.com", "Contact details for Co", _
sb.ToString())
sc.Send(msg)
Catch ex As Exception
' something bad happened
Response.Write("Something bad happened! - please try again")
Finally
Multiview1.SetActiveView(ViewConfirmation)
If Not msg Is Nothing Then msg.Dispose()
End Try
End If
End Sub
Protected Sub Page_Load (ByVal sender As Object, ByVal e As EventArgs)
If Not IsPostBack Then
Try
Multiview1.SetActiveView(ViewForm)
Catch ex As Exception
' something bad happened
Response.Write("Something bad happened! - please try again")
End Try
End If
End Sub
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:MultiView runat="server" id="MultiView1">
<asp:View runat="server" id="ViewForm">
<asp:AccessDataSource ID="AccessDataSource2bd" runat="server" DataFile="../app_data/bw_data.mdb" SelectCommand="SELECT * FROM student WHERE student_ID = 92">
</asp:AccessDataSource>
<asp:FormView runat="server" id="FormView2" DataSourceID="AccessDataSource2bd" DataKeyNames="student_ID" DefaultMode="ReadOnly">
<ItemTemplate >
<asp:Label id="first_nameTextBox" runat="server" Text='<%# Eval("first_name") %>' />,
</ItemTemplate >
</asp:FormView>
<asp:Table runat="server" id="Table2">
<asp:TableRow runat="server">
<asp:TableCell runat="server" HorizontalAlign="Left" height="20px">
<asp:Button id="UpdateButton" runat="server" CommandName="Update" onclick="btnSubmit_click" Text="Send Email"/>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</asp:View>
<asp:View runat="server" id="ViewConfirmation">
<p>An email has been sent, and copied to you, confirming all current contact details.</p>
</asp:View>
<p></p>
</asp:MultiView>
</form>
</body>
</html>
Thanks
Ant
Try this:
dim tb as TextBox = FormView2.Row.FindControl("first_nameTextBox")
sb.Append("Name : " + tb.Text + vbCrLf)

Dynamically Add Text Files to DDL in ASP & VB

I am looking to update one of my DDL's functionality by making it dynamically update so if the user adds more files, the drop down will pick this up.
At present my drop down list is pulling from VB code behind, as shown below:
Public Sub DDL_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim ddl As DropDownList = CType(sender, DropDownList) 'item is already dropdownlist
Dim ctl As TextBox = DirectCast(ddl.NamingContainer.FindControl("eTemplate"), TextBox)
If ddl.SelectedValue = 1 Then
ctl.Text = File.ReadAllText("e:Documents\Visual Studio 2013\Projects\Web\Templates\Down.txt")
ElseIf ddl.SelectedValue = 2 Then
ctl.Text = File.ReadAllText("e:Documents\Visual Studio 2013\Projects\Web\Templates\Up.txt")
Else
ctl.Text = ""
End If
End Sub
At the moment I have hard coded in the functionality for the VB to grab specific .txt files, how can I get this to update dynamically from a folder of .txt files?
Thanks for looking.
Here is some sample code for you. This demo uses an UpdatePanel and a Timer to refresh the DropdownList every 5 seconds.
Add a new aspx file to your Web Application and the following code:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Demo.aspx.vb" Inherits="Zpk_Test2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Asynchronous Update Demo</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager1" />
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" /><br />
<asp:Timer runat="server" ID="Timer1" Interval="5000" Enabled="true" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="DropDownList1" />
</Triggers>
</asp:UpdatePanel>
<asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" Width="300" Height="250" />
</form>
</body>
</html>
This is the code-behind:
Partial Class Demo
Inherits System.Web.UI.Page
Private Const FolderName As String = "C:\Temp" '<-- replace with your folder name
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
RefreshDropDownList()
OpenSelectedFile()
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
' this event is fired everytime a timer ticks.
' refresh your dropdown list here.
RefreshDropDownList()
End Sub
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
OpenSelectedFile()
End Sub
Private Sub RefreshDropDownList()
Dim currentSelected As String = DropDownList1.SelectedValue
DropDownList1.DataSource = IO.Directory.GetFiles(FolderName, "*.txt").Select(Function(f) IO.Path.GetFileName(f)).ToList
DropDownList1.DataBind()
DropDownList1.SelectedValue = currentSelected
End Sub
Private Sub OpenSelectedFile()
Dim fileName As String = IO.Path.Combine(FolderName, DropDownList1.SelectedValue)
TextBox1.Text = IO.File.ReadAllText(fileName)
End Sub
End Class

asp:Gridview getting focused column/lifecycle issue

I am working on a proof of concept (POC) GridView for a much more complex set of functionality where any given cell is filled with a textbox whether it is in normal or edit mode. When any given textbox receives focus (tab or mouse), the row is set to an edit state and it's corresponding textbox in edit mode should receive focus. Once that textbox loses focus it should cause an update on that row. I have the POC working except finding a viable way to select the column ("textbox") that received focus which I believe is a lifecycle issue, but am not coming up with any good workarounds. Please remember this is a POC and there are things I have done that may not be best practice as a quick and dirty way to get it working. I would greatly appreciate any suggestions.
Form:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="StandardContactEditor.aspx.vb" Inherits="EditableGridView.StandardContactEditor" EnableEventValidation="false" %>
<!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="contactsDataGrid"
AllowPaging="true" PageSize="5"
DataKeyNames="ID"
AutoGenerateColumns="false"
runat="server">
<Columns>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:TextBox ID="txtFirstName" Text='<%# Bind("FirstName") %>' runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtFirstNameEdit" Text='<%# Bind("FirstName") %>' runat="server" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Name">
<ItemTemplate>
<asp:TextBox ID="txtLastName" Text='<%# Bind("LastName") %>' runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtLastNameEdit" Text='<%# Bind("LastName") %>' runat="server" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
Code:
Imports FileHelpers
Public Class StandardContactEditor
Inherits System.Web.UI.Page
private fileName As String = "C:\TestFiles\TestContacts.csv"
Private records As List(Of ContactCSV)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack
BindGridData()
End If
End Sub
Private Sub BindGridData()
PopulateRecords()
Me.contactsDataGrid.DataSource = records
Me.contactsDataGrid.DataBind()
End Sub
Protected Sub RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles contactsDataGrid.RowDataBound
e.Row.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)
If Not ((e.Row.RowState = DataControlRowState.Edit) _
Or (e.Row.RowState = (DataControlRowState.Alternate Or DataControlRowState.Edit)))
Try
' First Name Column
Dim firstNameTb As TextBox = e.Row.FindControl("txtFirstName")
' firstNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)
' ISSUE CAUSED BY APPENDING "000" - Used for col/textbox identification
firstNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString() + "000", false)
Catch ex As Exception
Console.WriteLine()
End Try
Try
Dim lastNameTb As TextBox = e.Row.FindControl("txtLastName")
' lastNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)
' ISSUE CAUSED BY APPENDING "001" - Used for col/textbox identification
lastNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString() + "001", false)
Catch ex As Exception
End Try
End If
End Sub
Protected Sub RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs) Handles contactsDataGrid.RowEditing
contactsDataGrid.EditIndex = (e.NewEditIndex / 1000)
Dim col As Integer = (e.NewEditIndex Mod 1000)
' contactsDataGrid.EditIndex = e.NewEditIndex
BindGridData()
Dim fntb As TextBox = contactsDataGrid.Rows(contactsDataGrid.EditIndex).FindControl("txtFirstNameEdit")
fntb.Attributes("onblur") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Update$" + contactsDataGrid.EditIndex.ToString(), false)
' fntb.Focus()
Dim lntb As TextBox = contactsDataGrid.Rows(contactsDataGrid.EditIndex).FindControl("txtLastNameEdit")
lntb.Attributes("onblur") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Update$" + contactsDataGrid.EditIndex.ToString(), false)
' lntb.Focus()
If(col = 0)
fntb.Focus()
Else If(col = 1)
lntb.Focus()
End If
End Sub
Protected Sub RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs) Handles contactsDataGrid.RowUpdating
' AT THIS POINT THE EDIT FIELDS ARE NOT VISIBLE AND AN EXCEPTION IS THROWN WHEN TRYING TO RETRIEVE THOSE TEXTBOXES
' Trying to override here
contactsDataGrid.EditIndex = (contactsDataGrid.EditIndex / 1000)
PopulateRecords()
Dim id As String = contactsDataGrid.DataKeys(e.RowIndex).Value.ToString()
Dim record As ContactCSV = records.Where(Function(x) x.ID = id).SingleOrDefault()
Dim firstNameTb As TextBox = contactsDataGrid.Rows(e.RowIndex).FindControl("txtFirstNameEdit")
record.firstName = firstNameTb.Text
Dim lastNameTb As TextBox = contactsDataGrid.Rows(e.RowIndex).FindControl("txtLastNameEdit")
record.lastName = lastNameTb.Text
WriteRecordsToFile()
contactsDataGrid.EditIndex = -1
' update the actual data
contactsDataGrid.DataSource = records
contactsDataGrid.DataBind()
End Sub
Protected Sub SelectedColumn(ByVal Sender As Object, ByVal e As EventArgs)
Console.WriteLine()
End Sub
Private Sub PopulateRecords()
Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
Try
Dim objs As ContactCSV() = fileEngine.ReadFile(fileName)
records = objs.ToList()
Catch ex As exception
End Try
End Sub
Private Sub WriteRecordsToFile()
Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
fileEngine.WriteFile(fileName, records)
End Sub
End Class
This was a classic case of over-thinking a solution with a combination of an unfamiliar technology. The idea was to build a highly responsive (per field edit) page. Rather than mix any built-in GridView functionality, a simple OnTextChanged worked as I expected after everything else was stripped out. The problem turned out with the previous code posted is after an OnBlur, with the column identification parts in place, a row was set to Alternate state rather than Alternate Or Edit state.
Form:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="StandardContactEditor.aspx.vb" Inherits="EditableGridView.StandardContactEditor" EnableEventValidation="true" %>
<!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="contactsDataGrid"
AllowPaging="true" PageSize="5"
DataKeyNames="ID"
AutoGenerateColumns="false"
runat="server">
<Columns>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:TextBox ID="txtFirstName" Text='<%# Bind("FirstName") %>' OnTextChanged="textBox_TextChanged" AutoPostBack="true" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Name">
<ItemTemplate>
<asp:TextBox ID="txtLastName" Text='<%# Bind("LastName") %>' OnTextChanged="textBox_TextChanged" AutoPostBack="true" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Phone Number">
<ItemTemplate>
<asp:TextBox ID="txtPhoneNumber" Text='<%# Bind("PhoneNumber") %>' OnTextChanged="textBox_TextCHanged" AutoPostBack="true" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
Code:
Imports FileHelpers
Public Class StandardContactEditor
Inherits System.Web.UI.Page
private fileName As String = "C:\TestFiles\TestContacts.csv"
Private records As List(Of ContactCSV)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack
BindGridData()
End If
End Sub
Private Sub BindGridData()
PopulateRecords()
Me.contactsDataGrid.DataSource = records
Me.contactsDataGrid.DataBind()
End Sub
Protected Sub textBox_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
PopulateRecords()
Dim tb as TextBox = sender
Dim row As GridViewRow = tb.Parent.Parent
Dim record As ContactCSV = records.Where(Function(x) x.ID = row.RowIndex).SingleOrDefault()
Dim firstNameTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtFirstName")
record.firstName = firstNameTb.Text
Dim lastNameTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtLastName")
record.lastName = lastNameTb.Text
Dim phoneNumberTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtPhoneNumber")
record.PhoneNumber = phoneNumberTb.Text
WriteRecordsToFile()
End Sub
Private Sub PopulateRecords()
Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
Try
Dim objs As ContactCSV() = fileEngine.ReadFile(fileName)
records = objs.ToList()
Catch ex As exception
End Try
End Sub
Private Sub WriteRecordsToFile()
Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
fileEngine.WriteFile(fileName, records)
End Sub
End Class

Gridview inside UpdatePanel on ModalDialog not updating after AsyncFileUpload

I have a GridView inside an update panel, and a AsyncFileUpload (outside the Update Panel) that I am using to upload Images. All these are in a ASPX page called using the SHOWMODALDIALOG.
What I'm tying to achieve:
1. As soon as the file upload completes, the Update Panel updates, and the gridview displays the image the user just added.
The problems I'm facing:
1. The Gridview is not refreshing, even though I have a Databind event after the file is uploaded to the database. The Update Panel is getting refreshed through the __doPostBack('UpdatePanelID',' ') in a JS called by OnClientUploadComplete (I'm checking this through a Label showing current time in the Update Panel)
2. The ModalDialog is opening a new page whenever I click on 'Save Changes' or 'Cancel' button after adding an Image. If I just open the window and click these buttons, they work fine. I did try including <base target="_self" /> in the <head>, and finally settled with window.name="xxx" onload body.
Any help is appreciated.
My code:
ASPX
<%# Page Language="VB" AutoEventWireup="false" CodeFile="RCMT0032.aspx.vb" Inherits="RCWKSHEET.RCMT0032" EnableEventValidation="false"%>
<%# Register TagPrefix="asp" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit"%>
<html>
<head>
<base target="RCMT0032" />
<title>RCMT0032</title>
<script type="text/javascript">
function readpasseddata() {
window.name = 'RCMT0032';
var rpt = window.dialogArguments;
document.getElementById("HiddenReport").value = rpt;
}
function UploadComplete(sender, args) {
__doPostBack('gvupd', '');
}
</script>
</head>
<body onload="readpasseddata()" >
<form id="Form1" method="post" runat="server" target="RCMT0032" >
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"></asp:ToolkitScriptManager>
<asp:AsyncFileUpload id="BrowserHidden" Width="1" runat="server" OnClientUploadComplete="UploadComplete" OnUploadedComplete="BrowserHidden_UploadedComplete"/>
<button class="ActionButton" id="btnSave" runat="server">Save & Exit</button>
<button class="ActionButton" id="btnClose" runat="serverCancel</button>
<asp:UpdatePanel id="gvupd" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
<asp:GridView id="GridView1" Runat="server" AutoGenerateColumns="False"
AllowPaging="false" EnableViewState="true" datakeynames="Seq">
<Columns>
<asp:TemplateField HeaderText="Comments">
<ItemTemplate><asp:TextBox ID="comments" Enabled="true" MaxLength="249" TextMode="MultiLine" Text='<%# Eval("Comments") %>'/>
</asp:TemplateField>
<asp:TemplateField HeaderText="Picture">
<ItemTemplate><asp:HyperLink id="PictHyper" runat="server" Target="_blank" ImageUrl='<%# String.Format("RCMT0033.aspx?report={0}&seq={1}", Eval("ReportNumber"), Eval("Seq"))%>' NavigateUrl='<%# String.Format("RCMT0034.aspx?report={0}&seq={1}", Eval("ReportNumber"), Eval("Seq"))%>' /></ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Delete">
<ItemTemplate><asp:CheckBox runat="server" ID="DeleteCB" /></ItemTemplate>
</asp:TemplateField></Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
THE CODE BEHIND
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoaD
If Not IsPostBack Then
LoadData()
DataBind()
Else
With ViewState
_intReportNumber = CInt(.Item("Report"))
_strVendorNumber = CStr(.Item("VendorNumber"))
_strStatus = CStr(.Item("Status"))
End With
End If
End Sub
Public Sub LoadData()
//GET DATA INTO DATATABLE DT
GridView1.DataSource = dt
GridView1.DataBind()
Catch err As Exception
Throw err
End Try
End Sub
Protected Sub UploadData()
If BrowserHidden.PostedFile IsNot Nothing AndAlso BrowserHidden.PostedFile.FileName <> "" Then
Try
//UPLOAD STUFF
GridView1.DataBind()
Catch ex As Exception
End Try
End If
End Sub
Protected Sub btnClose_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.ServerClick
canceladd()
ScriptManager.RegisterStartupScript(Page, Me.GetType(), "onclick", "window.open('','_self',''); window.close();", True)
End Sub
Protected Sub BrowserHidden_UploadedComplete(ByVal sender As System.Object, ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs)
UploadData()
End Sub
Protected Sub gvupd_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles gvupd.Load
Label1.Text = DateTime.Now.ToString()
End Sub
Protected Sub btnSave_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.ServerClick
FinalizeAdd()
Page.ClientScript.RegisterStartupScript(Me.GetType(), "onclick", "window.open('','_self',''); window.close();", True)
End Sub
For your #2 issue, I don't think you can reload/refresh the modal window with either client side or server side script. To archive the same or similar result, you can have the upload control to close the modal window and return a value to indicate reopening is needed. then in the parent window, you can use a loop to open it as needed. if user clicks on close button on modal window or the X button on top right, the modal will not be reopened because it does not sent the "reopen" value back to parent.
ParentPage.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="ParentPage.aspx.cs" Inherits="WebApplication1.ParentPage" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function popModal(){
var val = window.showModalDialog('ModalChild.aspx', '', '');
while (val == "reopen") {
val = window.showModalDialog('ModalChild.aspx', '', '');
}
}
</script>
</head>
<body>
<input type='button' value='Pop Modal' onclick='popModal();' />
</body>
</html>
ModalChild.aspx
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function closeAndReOpen(){
window.returlValue = "reopen";
window.close();
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<div>
<asp:AsyncFileUpload ID="AsyncFileUpload1" runat="server" OnClientUploadComplete="closeAndReOpen();"
OnUploadedComplete="AsyncFileUpload1_UploadedComplete" />
<input type='button' value='Close' onclick='window.close();' />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView runat="server" ID="GridView1" AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img runat="server" id="img" /></ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="AsyncFileUpload1" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
ModalChild.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.UI.HtmlControls;
namespace WebApplication1
{
public partial class ModalChild: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
LoadGrid();
}
}
protected void LoadGrid()
{
var files = new DirectoryInfo(Server.MapPath("Data")).GetFiles("*.png");
GridView1.DataSource = files;
GridView1.DataBind();
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var fi = e.Row.DataItem as FileInfo;
var img = e.Row.FindControl("img") as HtmlImage;
img.Src = #"Data\" + fi.Name;
}
}
protected void AsyncFileUpload1_UploadedComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
if (AsyncFileUpload1.PostedFile != null)
{
var savePath = Server.MapPath(#"Data\" + Guid.NewGuid().ToString() + ".png");
AsyncFileUpload1.SaveAs(savePath);
}
}
}
}

Resources