ASP.NET ICallbackEventHandler and ASP.net Ajax updatepanel - asp.net

i would like to use ajax UpdatePanel and ICallbackEventHandler on one page. Each will handle individual part of page, they are not related to each one.
If I remove UpdatePanel, ICallbackEventHandler is working. If I remove ICallbackEventHandler, update panel is working, but they are not working altogether :(
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default"
EnableEventValidation="false" %>
<!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 src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
</head>
<body>
<script type="text/ecmascript">
function BootX() {
XUpdate();
}
function XUpdate() {
X_CallServer("", "");
}
function X_ReceiveServerData(rValue) {
$("#a").html(rValue);
}
</script>
<form id="form1" runat="server">
<div id="a">
</div>
<asp:ScriptManager runat="server" ID="ScriptManager1" />
<div>
<asp:Timer ID="Timer1" runat="server" Interval="100" OnTick="Timer1_Tick">
</asp:Timer>
<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
<ContentTemplate>
<asp:DropDownList runat="server" ID="ddl">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
<script type="text/ecmascript">
BootX();
</script>
</body>
</html>
And code behind:
public partial class _Default : System.Web.UI.Page, ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "X_ReceiveServerData", "context", true);
String callbackScript = string.Format("function X_CallServer(arg, context)" + "{{ {0} ;}}", cbReference);
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "X_CallServer", callbackScript, true);
ScriptManager1.RegisterAsyncPostBackControl(Timer1);
}
private string result = "";
public void RaiseCallbackEvent(string eventArgument)
{
// pretending some time consuming work
for (int i = 0; i < 1000000; i++) for (int j = 0; j < 100; j++) ;
result = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa";
}
public string GetCallbackResult()
{
return result;
}
protected void Timer1_Tick(object sender, EventArgs e)
{
UpdatePanel1.Update();
Timer1.Enabled = false;
// pretending some time consuming work
for (int i = 0; i < 1000000; i++) for (int j = 0; j < 1000; j++) ;
ddl.Items.Add("Item 1");
ddl.Items.Add("Item 2");
ddl.Items.Add("Item 3");
}
}
The code above is just concept. I already have 5 control using ICallbackEventhandler on one page and they are working perfectly, now I need to add one new control to page which is using updatepanel, and it broke all of my other "ICallbackEventhandler" controls.

After few hours I found solution.
Instead of
<script type="text/ecmascript"> BootX();</script>
I used
function pageLoad(sender, args) {setTimeout("BootX()", 25); }
And it's working. The solution was quite easy :) UpdatePanel uses Postback, everytime when postback is made pageLoad method is called and here we call callback func.

Related

Can a Templated User Control be used for data entry?

I've found code examples that demonstrate templated user controls. They work fine for displaying data, but I can't get them to work for entering data. I have a TextBox in my template, and can change the value in it, but I can't get that changed value in my code. I attempt to get the user control's values in a button click handler, but I always get just the initial value. Also, when I click the button, the templated user control's value(s) are reset. Is data entry supposed to work with templated user controls?
My code is similar to the MSDN topic "How to: Create Templated ASP.NET User Controls".
Default.aspx ===============================
<%# Page Language="C#" %>
<%# Register TagPrefix="uc" tagname="TemplateTest" Src="TemplatedUC.ascx" %>
<!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">
<script runat="server">
protected void Page_Load()
{
DataBind();
}
protected void ButtonShowContent_Click(object sender, EventArgs e)
{
ContentLabel.Text = string.Format("Index: {0} - Message: {1}<br>", TemplateTest1.Index, TemplateTest1.Message);
}
</script>
<head runat="server">
<title>Templated User Control Test</title>
</head>
<body>
<h1>Testing Templated User Control</h1>
<form id="Form2" runat="server">
<uc:TemplateTest ID="TemplateTest1" runat="server">
<MessageTemplate>
Index: <asp:Label runat="server" ID="Label1" Text='<%# Container.Index %>' /><br />
Message: <asp:TextBox runat="server" ID="Label2" Text='<%# Container.Message %>' /><br />
</MessageTemplate>
</uc:TemplateTest>
<asp:Button ID="ButtonShowContent" runat="server" Text="Show Content" onclick="ButtonShowContent_Click" />
<asp:Label ID="ContentLabel" runat="server" Text=" " Width="100%" />
</form>
</body>
</html>
TemplatedUC.ascx ============================
<%# Control Language="C#" ClassName="TemplatedUC" %>
<%# Import Namespace="System.ComponentModel" %>
<script runat="server">
private ITemplate messageTemplate = null;
private MessageContainer container = new MessageContainer(1, "Initial Text");
[ TemplateContainer(typeof(MessageContainer)) ]
[ PersistenceMode(PersistenceMode.InnerProperty) ]
public ITemplate MessageTemplate {
get
{
return messageTemplate;
}
set
{
messageTemplate = value;
}
}
public int Index
{
get { return container.Index; }
set { container.Index = value; }
}
public string Message
{
get { return container.Message; }
set { container.Message = value; }
}
void Page_Init() {
if (messageTemplate != null) {
messageTemplate.InstantiateIn(container);
PlaceHolder1.Controls.Add(container);
}
}
public class MessageContainer: Control, INamingContainer {
private int m_index;
private String m_message;
internal MessageContainer(int index, String message)
{
m_index = index;
m_message = message;
}
public int Index {
get { return m_index; }
set { m_index = value; }
}
public String Message
{
get { return m_message; }
set { m_message = value; }
}
}
</script>
<asp:Placeholder runat="server" ID="PlaceHolder1" />
If you run this and change the value for 'Message', then when you click the button, the data will be displayed. Thank you.

Click event on div in asp.net

I have a div in default.aspx with img inside as follow
<div id="sTab" class="tabs firsttab" runat="server">
<asp:Image ID="sTabImg" src="images/home.png" runat="server" />
Activities
</div>
I want to perform some action on click of the div in ASP.NET (not in javascript).
I tried the following
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
sTabImg.Attributes["onclick"] = ClientScript.GetPostBackEventReference(this, "ClickDiv");
}
protected void ClickDiv()
{
Label2.Text = "helo got it";
}
The page is getting refreshed and when i debugged the issue, its not entering the ClickDiv function..What wrong here..
From Here
public partial class _Default : System.Web.UI.Page, IPostBackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
div1.Attributes["onclick"]=ClientScript.GetPostBackEventReference(this,"ClickDiv");
}
protected void Div1_Click()
{
// Do something
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
if (!string.IsNullOrEmpty(eventArgument))
{
if (eventArgument == "ClickDiv")
{
Div1_Click();
}
}
}
#endregion
}
You have to implement the IPostBackEventHandler Interface.
Why not use ImageButton?
<%# Page Language="C#" AutoEventWireup="True" %>
<!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>
<title>ImageButton Sample</title>
<script language="C#" runat="server">
void ImageButton_Click(object sender, ImageClickEventArgs e)
{
Label1.Text = "You clicked the ImageButton control at the coordinates: (" +
e.X.ToString() + ", " + e.Y.ToString() + ")";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<h3>ImageButton Sample</h3>
Click anywhere on the image.<br /><br />
<asp:ImageButton id="imagebutton1" runat="server"
AlternateText="ImageButton 1"
ImageAlign="left"
ImageUrl="images/pict.jpg"
OnClick="ImageButton_Click"/>
<br /><br />
<asp:label id="Label1" runat="server"/>
</form>
</body>
</html>
And you can see some examples here.

ScriptManager.RegisterClientScriptBlock registering scripts twice

On the OnPreRender of my custom server control, I am registering an alert to popup everytime the page is loaded after a partial postback (add_pageLoaded(function() { alert('Hi')})). I only want this to be called once, but its gets called as many times as there has been partial postbacks. For example, in the code below, if you open the page and click "Click me" you get one alert, click again and you will get two alerts, three --> three alerts and so forth. My understanding was that ScriptManager.RegisterClientScriptBlock, using the scriptKey parameter was suppose to check if the script has already been registered, and if so, dont register it again.
I cannot register this script on !IsPostBack because my custom control will be inserted during Postbacks into pages, so using !IsPostBack will not include my script.
Here is a simple example of this problem:
ASPX:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RegisterClientScriptExperimentation._Default" %>
<%# Register Assembly="RegisterClientScriptExperimentation" Namespace="RegisterClientScriptExperimentation" TagPrefix="cc" %>
<!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">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"/>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Panel ID="panel" runat="server"/>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
namespace RegisterClientScriptExperimentation
{
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
panel.Controls.Add(new CustomControl());
}
}
public class CustomControl : CompositeControl
{
private Button button;
public CustomControl()
{
button = new Button();
button.Text = "Click me";
}
protected override void CreateChildControls()
{
Controls.Clear();
Controls.Add(button);
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
StringBuilder _text = new StringBuilder();
_text.Append("var prm = Sys.WebForms.PageRequestManager.getInstance();");
_text.Append("prm.add_pageLoaded(function() { alert('Page Loaded'); });");
if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);
else
Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
}
}
}
if(!Page.ClientScript.IsClientScriptBlockRegistered("customControlScript") && !Page.IsPostBack)
{
if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);
else
Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
}
I found the solution to this.
In your page events, after you execute whatever you need to do, you need to remove the function from the event which you hooked into.
For example:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(DoSomething);
function DoSomething() {
alert('Hello');
Sys.WebForms.PageRequestManager.getInstance().remove_pageLoaded(DoSomething);
}

how to retrieve TextBox control's ClientID within the ListView's ItemDataBound event?

I am having trouble retrieving a TextBox control's ClientID value from a ListView control.
I thought this syntax would return me the ClientID fine(very strange):
((TextBox)e.Item.FindControl("amount")).ClientID;
but it keeps throwing this exception:
"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
Any help is greatly appreciated.
Below is my code:
aspx:
<asp:ListView ID="categories" runat="server"
ClientIDRowSuffix="ID"
ItemPlaceholderID="categoryItem"
DataKeyNames="ID" onitemdatabound="categories_ItemDataBound">
<ItemTemplate>
<div class="category">
<asp:TextBox ID="amount" runat="server" />
</div>
</ItemTemplate>
</asp:ListView>
codebehind:
public string AmountTextBoxClientID { get; set; }
protected string GetAmountTextBoxClientID()
{
return this.AmountTextBoxClientID;
}
protected void categories_ItemDataBound(object sender, ListViewItemEventArgs e)
{
switch (e.Item.ItemType)
{
case ListViewItemType.DataItem:
TextBox amountTextBox = (TextBox)e.Item.FindControl("amount");//this line excutes without any error
amountTextBox.Text = categoryAmount.ToString("C");
amountTextBox.Attributes.Add("readonly", "readonly");
this.AmountTextBoxClientID = amountTextBox.ClientID; //this line keeps throwing the OutOfRange exception
break;
}
}
Im afraid I cant pinpoint your problem but i drew up a page based on what you've given and pasted it below. It does NOT error.
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public string AmountTextBoxClientID { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("column1");
DataRow dr = dt.NewRow();
dr[0] = "some data";
dt.Rows.Add(dr);
ListView1.DataSource = dt;
ListView1.DataBind();
}
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
TextBox tbAmount = (TextBox)e.Item.FindControl("amount");
this.AmountTextBoxClientID = tbAmount.ClientID;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListView ID="ListView1" runat="server" onitemdatabound="ListView1_ItemDataBound">
<ItemTemplate>
<asp:TextBox ID="amount" runat="server" />
</ItemTemplate>
</asp:ListView>
</div>
</form>
</body>
</html>

How do I bind an ASP.net ajax AccordionPane to an XMLDatasource?

I've got an angry boss that will beat me down if I waste another day on this :-P Many karma points to the ajax guru who can solve my dilemma.
But more detail: I want to have an AccordionPane that grabs a bunch of links from an XML source and populate itself from said source.
There might be a sexier way, but this works. Populate your data source however you wish. This was just for demo purposes. Ditto for PrettyTitle() Key is to remember there are two item types in the accordion.
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Accordion Binding</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="AjaxScriptManager" runat="server">
</asp:ScriptManager>
<div>
<cc1:Accordion ID="AccordionControl" runat="server"
onitemdatabound="AccordionControl_ItemDataBound">
<Panes></Panes>
<HeaderTemplate>
<asp:Label ID="HeaderLabel" runat="server" />
</HeaderTemplate>
<ContentTemplate>
<asp:Literal ID="ContentLiteral" runat="server" />
<asp:HyperLink ID="ContentLink" runat="server" />
</ContentTemplate>
</cc1:Accordion><asp:xmldatasource runat="server" ID="RockNUGTwitter" ></asp:xmldatasource>
</div>
</form>
</body>
</html>
And codebehind is :
Using System;
using System.Web.UI.WebControls;
using System.Xml;
namespace Ajaxy
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Fill();
}
private void Fill()
{
PopulateDataSource();
AccordionControl.DataSource = RockNUGTwitter.GetXmlDocument().SelectNodes("//item");
AccordionControl.DataBind();
}
private void PopulateDataSource()
{
XmlDocument RockNugTwitterRSSDocument = new XmlDocument();
RockNugTwitterRSSDocument.Load("http://twitter.com/statuses/user_timeline/15912811.rss");
RockNUGTwitter.Data = RockNugTwitterRSSDocument.OuterXml;
}
protected void AccordionControl_ItemDataBound(object sender, AjaxControlToolkit.AccordionItemEventArgs e)
{
XmlNode ItemNode = (XmlNode)e.AccordionItem.DataItem;
if(e.AccordionItem.ItemType == AjaxControlToolkit.AccordionItemType.Content)
{
HyperLink ContentLink = (HyperLink)e.AccordionItem.FindControl("ContentLink");
ContentLink.NavigateUrl = ItemNode.SelectSingleNode("link").InnerText;
Literal ContentLiteral = (Literal)e.AccordionItem.FindControl("ContentLiteral");
ContentLiteral.Text = ItemNode.SelectSingleNode("title").InnerText;
ContentLink.Text = "Link";
}
else if(e.AccordionItem.ItemType == AjaxControlToolkit.AccordionItemType.Header)
{
Label HeaderLabel = (Label) e.AccordionItem.FindControl("HeaderLabel");
HeaderLabel.Text = PrettyTitle(ItemNode.SelectSingleNode("title").InnerText);
}
}
private string PrettyTitle(string FullItem)
{
string PrettyString = FullItem.Replace("RockNUG: ", "");
string[] Words = PrettyString.Split(' ');
const int MAX_WORDS_TOSHOW = 4;
int WordsToShow = MAX_WORDS_TOSHOW;
if(Words.Length < MAX_WORDS_TOSHOW)
{
WordsToShow = Words.Length;
}
PrettyString = String.Join(" ", Words, 0, WordsToShow);
if (Words.Length > WordsToShow)
{
PrettyString += "...";
}
return PrettyString;
}
}
}

Resources