custom ListView inside Update panel not refreshing - asp.net

I'm trying to solve this problem.
I have an Accordion inside an UpdatePanel. Inside the Accordion control I dinamically create at most four AccordionPanes, each with a custom ListView that shows some image previews fetched from a database. Each preview is composed by a 160x120 ImageButton. When the user clicks on one of these buttons a popup is opened with the image at real size (by a Seadragon control); he can now rotate the image and save it back to the database. Now, after saving the image, I close the popup and submit a postback by generating a click event on a hidden button inside the UpdatePanel containing the Accordion, but even if I can step through the hidden button event code, the refresh doesn't take place. The hidden button was the last (and most effective) solution I've tried, without success. What am I missing ? (The absolute best solution would be refresh the only image that changed, because sometimes the ListView contains several previews).
This is the
<div>
<table class="style8">
<tr>
<td class="style2">
<asp:UpdatePanel ID="usersPanel" runat="server" >
<ContentTemplate>
<cc1:c1treeview ID="tvUsers" runat="server"
onselectednodeschanged="tvUsers_SelectedNodesChanged" AutoPostBack="True"
onnodecheckchanged="tvUsers_SelectedNodesChanged">
</cc1:c1treeview>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="imagesPanel" runat="server" UpdateMode="Always" >
<ContentTemplate>
<asp:Button ID="hiddenImageRefresh" runat="server" Text="Refresh"
style="display:none;" onclick="hiddenImageRefresh_Click" />
<ajaxToolkit:Accordion ID="accImages" runat="server" >
</ajaxToolkit:Accordion>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
</div>
And this is the code contained in the hidden button click event, code, that regularly runs when the popup closes. It simply extracts a user code (promo) and rebind the data (LoadImages)
protected void hiddenImageRefresh_Click(object sender, EventArgs e)
{
string promo = "";
if(Session[SessionVariables.CurrentPromoter] != null)
promo = Session[SessionVariables.CurrentPromoter].ToString();
LoadImages(promo, ddlImageType.SelectedValue);
}

Steps to refresh only updated image
Step#1: in JavaScript
//Take one global variable
var selectedImageId="";
Step#2: in JavaScript
//set above var with image id, When user clicks on the ImageButton, which is inside openPopup function
selectedImageId = this.id;
Step#3: in Code-Behind
protected void bSave_Click(object sender, EventArgs e) {
//SaveImage();
#region here get the imageUrl that needs to be updated and send as parameter in closePopup js function
var timeStamp = dImgTag.ToString("yyyyMMdd HH:mm:ss.fff") ;
var promoter = riga["PROMOTER"].ToString();
var pv = riga["PV"].ToString();
var imageUrl = string.Format("../Handlers/ImageLoader.ashx?id={0}&promo={1}&pv={2}", timeStamp, promoter, pv);
#endregion
ClientScriptManager csm = Page.ClientScript;
csm.RegisterStartupScript(Page.GetType(), "closeScript", "closePopup(true,'"+ imageUrl +"');", true);
}
Step#4: in JavaScript
function closePopup(refreshParent, imageUrl) {
if (refreshParent) {
//get the selectedImage and set the source with new url
var selectedImage = window.opener.document.getElementById(selectedImageId);
selectedImage.src = imageUrl;
}
window.close();
}

Related

Where to catch user control properties being wrapped to be loaded inside a modal?

I have a user control which has a public property (e.g. AlarmID) and this control is wrapped inside a div and when user presses a button on the page, in code-behind the public property of that user control becomes set. then a ScriptManager.RegisterStartupScript is called to show a modal popup which is a div wrapping that control.
My problem is that although in code-behind I first set the public property of that user control, but when the modal popup shows that user control, I cannot access that property
I used Control_PreRender, and Control_Load events but none of them were able to show the correct value of that property in a label inside that control.
For more clarification, here is my code in the code-behind of the control:
protected void Control_Load(object sender, EventArgs e)
{
lblAlarmCode.Text = alarmID.ToString();
}
public int AlarmID
{
get
{
return this.alarmID;
}
set
{
this.alarmID = value;
}
}
What is the exact life-cycle event in which I can catch the property to be shown correctly by that label?
Thanks
Make sure that the modal is attached to the <form> element on the page otherwise it will not be a part of the page lifecycle at all.
Just as a sample, not saying this is your code, but I had to use something similar in order to have <asp:Textbox> and <asp:Button> controls to be brought back and forth across the Request
ASPX code:
<asp:Panel runat="server" ID="pnlWorkItem">
<fieldset>
<legend></legend>
<label>Job Code</label>
<asp:DropDownList runat="server" ID="ddlJobCode" Width="50%" />
<label>Hours</label>
<asp:TextBox runat="server" ID="txtHours" />
</fieldset>
<fieldset>
<legend></legend>
<p><asp:Button runat="server" ID="btnAddWorkItem" OnClick="btnAddWorkItem_Click" text="Add Work Item" /></p>
</fieldset>
</asp:Panel>
Javascript:
$(function () {
var workItemPanel = $("#<%= pnlWorkItem.ClientID %>");
workItemPanel.hide();
$("#add-work").on("click", function () {
$(workItemPanel).dialog({
width: 450,
height: 300
}).parent().appendTo($("form:first"));
});
});
It will append your element to the form element generated by ASP.net and should have your properties set and carried across.
One solution is to set the label in setter. However there might be other solutions but this ways is just working.

Load specific part in webpage?

See below image first.
we have one sidebar navigation(ajax accordion control asp.net)
now when ever user click on link inside side bar related page(content) should display in Content goes here region.
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
what should be the way to achieve this functionality?
what should be the best suggestion for that?
EDIT: navigation tree is inside MasterPage and Content goes region is in side content page of master page
please suggest me.....
thank you so much....
The Easiest way is to Wrap your side navigation & the Content placeholder in an UpdatePanel. Set the TreeView in the side bar as the UpdateTrigger for the update Panel. But, this approach is a little inefficient.
A slightly better way is ti just wrap the Content Placeholder in an Update Panel, along with a HiddenField in it. Upon a selection in the sidebar, update the HiddenField Value with JavaScript and then refresh the update Panel.
According to:
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
And
sidebar tree view is in master page and Content goes here region is content page
If my understanding is correct, I think you do not need to place your TreeView control in your master page because you only want one page loading dynamically the content based on the selection of your tree view. So...Why is this important? Well if you place your tree view in your page you can use an UpdatePanel to avoid full posts.
Output of the following code
The following code covers the next points:
A TreeView control is embedded in a UserControl and placed in an ASPX page (left side)
The menu contorl exposes an event that is raised whenever the selected node changes, this event is handled in the ASPX page to dynamically load user controls depending on the user selection on the right side of the page, only one content is loaded at a time.
The controls are embedded in an UpdatePanel therefore you won't change your page and your back button in your browser won't be affected
Note: the user controls keep their state across post backs
(I'm not sure if this is the best way to do it, perhaps you could try to find a solution using only ajax, and avoid the use of the evil updata panels, but certainly this is a way to do it)
I'll try to simplify the code to reduce the size of the post, I will just post the code of one user control, the other one is exactly the same I just changed its title to difference them on the page
ASCX Menu
<asp:TreeView ID="TreeView1" runat="server" onselectednodechanged="Unnamed2_SelectedNodeChanged">
<Nodes>
<asp:TreeNode Text="link1" />
<asp:TreeNode Text="link2" />
</Nodes>
<SelectedNodeStyle Font-Bold="True" Font-Italic="True" />
</asp:TreeView>
ASCX Menu code behind
public event Action<string> MenuChanged = delegate { };
protected void Unnamed2_SelectedNodeChanged(object sender, EventArgs e)
{
this.MenuChanged(this.TreeView1.SelectedNode.Text);
}
ASPX
<asp:ScriptManager runat="server" ID="sm" />
<asp:UpdatePanel runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:HiddenField runat="server" ID="currentControl" />
<table border="0" cellpadding="0" cellspacing="0" width="90%" align="center">
<tr>
<td style="width:50%; background-color: Silver">
<menu:TreeViewMenu runat="server" ID="myTreeViewMenu" OnMenuChanged="myTreeViewMenu_MenuChanged" />
</td>
<td style="width:50%; background-color: Aqua">
<p>Result:</p>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Label ID="lblMessage" runat="server" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
ASPX code behind
protected void Page_Init(object sender, EventArgs e)
{
if (this.IsPostBack)
{
var cc = this.Request.Form["currentControl"];
if (!string.IsNullOrWhiteSpace(cc))
{
var uc = this.LoadControl(this.Server.HtmlDecode(cc));
this.myPanel.Controls.Add(uc);
}
}
}
protected void myTreeViewMenu_MenuChanged(string e)
{
this.myPanel.Controls.Clear();
switch (e)
{
case "link1":
var cc1 = "~/Content1.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc1);
var uc1 = this.LoadControl(cc1);
this.myPanel.Controls.Add(uc1);
this.lblMessage.Text = "Updated from: link1";
break;
case "link2":
var cc2 = "~/Content2.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc2);
var uc2 = this.LoadControl(cc2);
this.myPanel.Controls.Add(uc2);
this.lblMessage.Text = "Updated from: link2";
break;
default:
this.lblMessage.Text = "Updated from default: " + e;
break;
}
}
ASCX
<h1>Content 1</h1>
<asp:TextBox runat="server" ID="txt" />
<asp:Button Text="Process data..." runat="server" OnClick="button_Click" />
<asp:Button Text="Just post" runat="server" />
<asp:Label ID="lblMessage" runat="server" />
ASCX Code Behind
protected void button_Click(object sender, EventArgs e)
{
this.lblMessage.Text = this.txt.Text;
}
You can simply copy-paste this code to test it yourself, this should work
Jupaol's answer works fine but 1 thing need to mention, I came across the problem after implemented Jupaol's idea, the first time I called the user control immediately after I click menu, the button with in the ascx works fine, but if I switch to 2nd one, first click of the button on the 2nd control will not fire on first click, this is because we do not have a "static" ID of the control. It took me almost 3 days to finally figure out why this is happening. so here's part of my code to make. I'm leaving this message in hope that anyone who read this afterwards will make the use of it.
if (!string.IsNullOrEmpty(controlPath))
{
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
/**note below LastLoadedControl is anything that could
* be unique to the called control so every time when call back
* it will not confuse the back end so the first fire of eg. a button
* on that loaded control will work
*/
uc.ID = LastLoadedControl;
PlaceHolder1.Controls.Add(uc);
}
I'll also need to thank Jupaol's great contribution so that I can get my site running.

how to access iframe textbox id in current page?

Friends I have a Parent Page(default.aspx) that includes an iframe page(iframe.aspx) containing textbox in the field. The parent page contains the "Save" button. Now i want to get the values of iframe page while submitting the parent page. How can i access the iframe pages fields in parent page submit?
iframe.aspx page,,,,
In Iframe page i have two textbox,,
<asp:textbox id="txtfromdate" runat="server"></asp:textbox>
<asp:textbox id="txttodate" runat="server"></asp:textbox>
default.aspx page
<iframe id="iframebody" runat="server" src="iframe.aspx" style="width:900px; height:600px"></iframe>
<asp:button id="submit" text="save" runat="server" />
frdz how to access iframe page id(txtfromdate, txtTodate) in parrent page(default.aspx) when i click on button??
Try this javascript on the button click.
HTML
<input type="hidden" id="txtHidData" runat="server" />
Javascript
var iframe = document.getElementById('iframebody');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
var usernameTextBox = innerDoc.getElementById('txtfromdate');
document.getElementById ( "txtHidData" ).value = usernameTextBox.value;
C#
string valueInCodeBehind = txtHidData.Value;
You can not access iframe's content with server side code.
For accessing content of iframe, you should use javascript.
In jquery, you can access it :
var iFrameContent = $('#iframebody').content();
var fromDate = iFrameContent.find('#txtfromdate').val();
var toDate= iFrameContent.find('#txttodate').val();
store it in hidden fields on page, and then access in server side code
Place two hidden fields on your aspx page. like
<asp:HiddenField id="hdffromdate" runat="server"></asp:textbox>
<asp:HiddenField id="hdftodate" runat="server"></asp:textbox>
Set values in these hidden fields like
$('[id$=hdffromdate]').val(fromDate );
$('[id$=hdftodate]').val(toDate);
in your submit button click event handler
protected void submit_Click(object sender, EventArgs e)
{
var fromDate = Convert.ToDateTime(hdffromdate.Value);
var toDate = Convert.ToDateTime(hdftodate.Value);
//...
}

ASP.NET page content doesn't change

I created an application which has a menu where it's items are created dynamicly. The menu acts as a language menu.
<body runat="server">
<form id="Form1" runat="server">
<table class="TableLayout">
<tr>
<td class="TopNav" align="right">
<asp:Menu runat="server" ID="LanguageMenu" Orientation="Horizontal" OnMenuItemClick="LanguageMenu_MenuItemClick">
<LevelMenuItemStyles>
<asp:MenuItemStyle CssClass="TopNavItem" />
</LevelMenuItemStyles>
<StaticHoverStyle CssClass="TopNavItemHover" />
</asp:Menu>
</td>
</tr>
...
I use session variables to set my current language.
however if I click on the menu to change the session variable:
public void LanguageMenu_MenuItemClick(Object sender, MenuEventArgs e)
{
Session["language"] = e.Item.Text;
}
The page reloads with the following code:
sportsPath = String.Format(#"{0}{1}\Sports\", xmlPath, Session["language"]);
//create LeftNavigation
string[] sports = Directory.GetFiles(sportsPath);
LeftNavigation.Items.Clear();
foreach (string sport in sports)
{
string text = sport.Replace(sportsPath, "").Replace(".xml", "");
MenuItem item = new MenuItem();
item.Text = text;
LeftNavigation.Items.Add(item);
}
The thing is the content doesn't change, only after I click on something else.
If I skip through my code after clicking on the menuItem I can see that it passes the code and it should change, however for some reason the page needs another extra trigger to modify it's content.
I also see the page reloading so I don't understand why it's not changing immediatly. I guess I'm not understanding the asp.net logic just quite yet.
What am I doing wrong?
The Page_Load is triggered before the MenuItemClick event, thus causing your Session variable to be set after your page is updated.
To solve this, you could move your code in the Page_Load to the Page_PreRender event handler, which is fired after the MenuItemClick.
The solution to this is to Redirect the User to the same page after updating the language preference in Session.
public void LanguageMenu_MenuItemClick(Object sender, MenuEventArgs e)
{
Session["language"] = e.Item.Text;
Response.Redirct("samepage.aspx");
Response.End();
}

Working with Gridviews and File Transfers

I need to generate a Excel sheet during RunTime on a ItemCommand_click event in a GridView and transfer the file and then re-bind the GridView with the status change.
As we redirect the response with File transfer , How could I update the GridView?
I was looking to do something very similar on selected index change on the rows to output a reporting services report as a PDF. I was only able to get this to work with a response.redirect to another page that handled the output of the file. It looks like your issue really becomes the rebinding the grid after the status change, if you do a response.redirect, you can't touch your grid...
Take a look at this code. I found it on encosia.com. It looks like you might be able to use the iFrame for your output, and then you can use a JavaScript call to postback the page to rebind the grid maybe.
<html>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" />
<script language="javascript">
// Get a PageRequestManager reference.
var prm = Sys.WebForms.PageRequestManager.getInstance();
// Hook the _initializeRequest event and add our own handler.
prm.add_initializeRequest(InitializeRequest);
function InitializeRequest(sender, args)
{
// Check to be sure this async postback is actually
// requesting the file download.
if (sender._postBackSettings.sourceElement.id == "DownloadFile")
{
// Create an IFRAME.
var iframe = document.createElement("iframe");
// Get the desired region from the dropdown.
var region = $get("Region").value;
// Point the IFRAME to GenerateFile, with the
// desired region as a querystring argument.
iframe.src = "GenerateFile.aspx?region=" + region;
// This makes the IFRAME invisible to the user.
iframe.style.display = "none";
// Add the IFRAME to the page. This will trigger
// a request to GenerateFile now.
document.body.appendChild(iframe);
}
}
</script>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:DropDownList runat="server" ID="Region">
<asp:ListItem Value="N">North Region</asp:ListItem>
<asp:ListItem Value="W">West Region</asp:ListItem>
<asp:ListItem Value="SE">Southeast Region</asp:ListItem>
</asp:DropDownList>
<asp:Button runat="server" ID="DownloadFile" Text="Generate Report" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
The page that handles the download...
protected void Page_Load(object sender, EventArgs e)
{
string FileResponse;
string Region = Request.QueryString["Region"];
// Code here to fill FileResponse with the
// appropriate data based on the selected Region.
Response.AddHeader("Content-disposition", "attachment; filename=report.csv");
Response.ContentType = "application/octet-stream";
Response.Write(FileResponse);
Response.End();
}

Resources