Gridview inside UpdatePanel on ModalDialog not updating after AsyncFileUpload - asp.net

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);
}
}
}
}

Related

How to validate all controller before button call OnClientClick javascript event?

When btnSave Clicked, it will call function check().
If check() return true, the page will postback and call the btnSave_Click event.
But I think it should be check the RequiredFieldValidator first before it call fucntion check().
How can I fix it?
In Default.aspx
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="TestValidation._Default" %>
<!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>
<script type="text/javascript">
function check() {
return confirm("Real?");
}
</script>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1" Display="Dynamic" ValidationGroup="vldGrp">AA</asp:RequiredFieldValidator>
<asp:Button ID="btnSave" runat="server" ValidationGroup="vldGrp" Text="Save" OnClientClick="return check();" />
<asp:ValidationSummary ID="vldSum" runat="server" DisplayMode="List" ShowSummary="False" ValidationGroup="vldGrp" ShowMessageBox="True" />
</div>
</form>
</body>
</html>
In Default.aspx.vb
Partial Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
End Sub
End Class
Check for the required field validator inside the function first and then perform the operations inside the function as:
function check() {
var validation = <%= RequiredFieldValidator1.ClientID %>;
if(validation.isValid()){
return confirm("Real?");
}
}
If there are many required field validators, and you need to invoke all of those, try:
function check() {
if (Page_ClientValidate()) {
return confirm("Real?");
}
}
Or even based on the name of your ValidationGroup (incase you need to invoke only selected validators)
function check() {
if (Page_ClientValidate('your group name')) {
return confirm("Real?");
}
}
Or else you can also check for the validation on server side,
Sub ValidateBtn_Click(sender As Object, e As EventArgs)
Page.Validate()
If (Page.IsValid) Then
DoSomething()
End If
End Sub

How to set ASP.NET control property through IIf statement

I am not sure if things have changed after .NET 2.0 because in .NET 2.0 I used to be able to set something like this:
<asp:Panel runat="server" Visible='<%#IIf(Some condition here, "true", "false") %>' />
I did this all the time to have a clean code behind.
Currently I am working with .NET 3.0 and I cannot for the life of me get this working. The condition which i am evaluating is not accessing any data binding fields but is as simple as checking the property of an object in the code behind.
Can anyone suggest how this inline-code should look?
UPDATE:
Here is an example of what i am trying to do. I swear something like this used to work in .NET 2.0 but it does not work now:
<%# Page Language="C#" %>
<!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 runat="server">
protected bool IsValid() { return true; }
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label Text="123" runat="server" Visible=<%#iif(IsValid(), "true", "false")%>/>
</div>
</form>
</body>
</html>
<%# indicates that you databind the control/page. So either you do
Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Me.DataBind()
End Sub
or you do it in codebehind completely(what i prefer):
Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
MyPanel.Visble = YourCondition
End Sub
http://naspinski.net/post/inline-aspnet-tags-sorting-them-all-out-%283c25242c-3c253d2c-3c252c-3c252c-etc%29.aspx
You can use VB in markup and C# in codebehind
<%# Page Language="VB"
Sure.. Visual Studio goes crazy
<%# Page Language="VB" AutoEventWireup="true" CodeBehind="WebForm6.aspx.cs" Inherits="WebApplication1.WebForm6" %>
<asp:repeater id="rpt" runat="server">
<ItemTemplate>
<br />
<%# Container.DataItem %>
<br />
<%#IIf( CType(Container.DataItem, System.Int32) > 5 = 0, "true", "false") %>
<br />
<br />
</ItemTemplate>
</asp:repeater>
and C# in code behind
using System.Linq;
namespace WebApplication1
{
public partial class WebForm6 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
rpt.DataSource = Enumerable.Range(1, 29);
rpt.DataBind();
}
}
}
And what VS feels about it

Dropdownlist in a repeater, selected index changed not working

I have a repeater with a dropdownlist in it. When a user changes its index, I would like a label to change its value. (the ddlSizes values come from a MySQL DB)
Sizes.aspx
<asp:DropDownList ID="ddlSizes" runat="server" AutoPostBack="True" DataSourceID="objdsSizes" DataTextField="SizeName" DataValueField="SizeID" />
<asp:Label ID="lbldummy" runat="server" Text=""></asp:Label>
Sizes.aspx.vb
Protected Sub ddlSizes_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlSizes.SelectedIndexChanged
lbldummy = ddlSizes.value
End Sub
But the ddlSizes.SelectedIndexChanged isn't recognized. So the value of lbldummy won't change.
Any suggestions? Thank you.
You will want to create the handler for the DropDownList, within this you need to have code which will convert the sender into a DropDownList then get the parent control and convert it into the RepeaterItem. From this you can then reference any other controls within the RepeaterItem
Public Sub ddlSizes_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim ddlSizes As DropDownList = DirectCast(sender, DropDownList)
Dim ri As RepeaterItem = DirectCast(ddlSizes.Parent, RepeaterItem)
Dim lbldummy As Label = DirectCast(ri.FindControl("lbldummy"), Label)
lbldummy.Text = ddlSizes.SelectedValue
End Sub
Then on your ddlSizes DropDownList add OnSelectedIndexChanged="ddlSizes_SelectedIndexChanged" and make sure it has AutoPostBack="True" set
Text is probably the default property, but I'd still specify it:
lbldummy.Text = ddlSizes.value
but for this, you really don't need to do a postback, you can accomplish this through Javascript as well. doing something like this:
<asp:DropDownList ID="ddlSizes" runat="server" onchange="return ddlSizes_change(this);" DataSourceID="objdsSizes" DataTextField="SizeName" DataValueField="SizeID" />
function ddlSizes_change(dropdown)
{
document.getElementById('<%= lbldummy.ClientID %>').innerHTML =
dropdown.options[myindex].value
return true;
}
Here's an example (C# but easily adaptable to VB.NET). Notice how inside the DdlSizes_SelectedIndexChanged I use FindControl to find the corresponding label:
<%# Page Language="C#" %>
<script type="text/c#" runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
rep.DataSource = Enumerable.Range(1, 5);
rep.DataBind();
}
}
protected void DdlSizes_SelectedIndexChanged(object sender, EventArgs e)
{
var ddl = (DropDownList)sender;
var lbl = (Label)ddl.FindControl("lbldummy");
lbl.Text = ddl.SelectedValue;
}
</script>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="Form1" runat="server">
<asp:Repeater ID="rep" runat="server">
<ItemTemplate>
<asp:DropDownList ID="ddlSizes" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DdlSizes_SelectedIndexChanged">
<asp:ListItem Value="1" Text="item 1" />
<asp:ListItem Value="2" Text="item 2" />
<asp:ListItem Value="3" Text="item 3" />
</asp:DropDownList>
<asp:Label ID="lbldummy" runat="server" />
</ItemTemplate>
</asp:Repeater>
</form>
</body>
</html>

Asp.Net and Shadowbox

Trying to pop up an IFrame Shadowbox with Jquery from an asp:gridview datarow. I can't get the proper quotes into the string:
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount(\'"+
Eval("id", "Popup.aspx?id={0}")+"\');" %>' />
Parser Error Message: The server tag is not well formed.
Without the escaped single quotes (cannot work, but parses properly):
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount("+
Eval("id", "Popup.aspx?id={0}")+");" %>' />
Client-side HTML, as expected:
onclick="javascript:popAccount(Popup.aspx?id=3ce3b19c-1899-4e1c-b3ce-55e5c02f1);"
How do I get quotes into the Javascript?
Edit: added solution. This not very generic, since the databound types must be known in order to access the id property. The key (as defined in the GrodView's DataKeyNames parameter) does not seem to be exposed in the event argument. But it works.
protected void editGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
// do not look at header or footer
if (e.Row.RowType == DataControlRowType.DataRow)
{
ImageButton btn = e.Row.FindControl("btnPopup") as ImageButton;
if (btn != null)
{
btn.OnClientClick =
"javascript:popAccount('EditAccountPopup.aspx?"+
Constants.acctidParam+"="+
((tb_account)(e.Row.DataItem)).id.ToString()+"');";
}
}
Pick up the ImageButton in the GridView's rowdatabound event in the codebehind, and add the property from there.
But are you sure you need to use a server control? How about just a plain image? If you're "replacing" the click-behaviour of the ImageButton, it doesn't seem like you need it at all.
Update:
For the code-behind solution, I coded up this little sample (in VB.NET, sorry):
Private Sub gridview1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gridview1.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim btnEdit As ImageButton = CType(e.Row.Cells(0).FindControl("btnEdit"), ImageButton)
Dim strID As String = CType(e.Row.DataItem, Guid).ToString
btnEdit.Attributes.Add("onclick", String.Format("javascript:popAccount('Popup.aspx?id={0}');", strID))
End Select
End Sub
However, I'd still recommend you go with a simpler aproach, jQuery is excellent here. No
need for any code in your codebehind:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$("img.edit").click(function() {
var sID = this.id.replace('btnEdit_', '');
alert(sID); // Add your popup opening logic here...
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gridview2" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img id="btnEdit_<%#Container.DataItem %>" class="edit" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
If you want to keep your code the way it is, why not just do this?
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount(&quot"+
Eval("id", "Popup.aspx?id={0}")+"&quot);" %>' />

Editable gridview - what are the basics?

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

Resources