User Control in Repeater fires multiple events.

D

Dave A

I have a problem that I have boiled down to a very simple example.

I have a user control that displays a some data from a business object. On one screen I have a collection of these business objects and wish to display the user control multiple times. On this web page I simply bind the repeater to the data source and in the ItemDataBound event dynamically load the user control via "LoadControl()".

The user control contains an auto post back textbox. When the text in the textbox changes it is to update the database. (It is also to update the web page with the results of a calculation and thus the reason for the update on the _TextChange rather than updating on a submit button.)

The problem occurs when there are multiple user controls on the screen. The user can edit the textbox in a user control, the auto post back fires, the _TextChanged event is called and the database is updated. If the user were to then edit another textbox in another user control then not only does its _TextChange event get called but the first _TextChange event is raised again.

This means that if the user were to edit 9 user controls, then when the 10th is edited, 10 _TextChange events would be raised.

The _TextChange event sets of sophisticated chain of events. It should be raised only when required.

I have no idea why this is happening and no idea about how to solve it.

The code can be downloaded from www.tcpiq.com/temp/UserControlEvents.zip

The web page's source is

<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server">
</asp:Repeater>
</div>
</form>
</body>

and the code behind is

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Repeater1.ItemDataBound += new RepeaterItemEventHandler(Repeater1_ItemDataBound);

List<string> theData = new List<string>();
theData.Add("A");
theData.Add("B");
theData.Add("C");
theData.Add("D");

Repeater1.DataSource = theData;
Repeater1.DataBind();
}

void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
WebUserControl webUserControl = (WebUserControl)LoadControl(@"~\WebUserControl.ascx");
e.Item.Controls.Add(webUserControl);
}
}

The user control's source is

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" OnTextChanged="TextBox1_TextChanged"></asp:TextBox>

and the code behind is:

using System;

public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}

public void TextBox1_TextChanged(object sender, EventArgs e)
{
Response.Write(DateTime.Now.ToString() + " " + ((System.Web.UI.WebControls.TextBox) sender).ClientID.ToString() + " Text changed<br>");
}
}


Thanks in advance.

Dave A
 
D

Dave A

I am not sure whether anyone looked at this post - there were no replies. But for the record the answer is to setup the databinding in the web page in the OnInit

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
Repeater1.ItemDataBound += new RepeaterItemEventHandler(Repeater1_ItemDataBound);

// Create an abritary collection to bind to.
List<string> theData = new List<string>();
theData.Add("A");
theData.Add("B");
theData.Add("C");
theData.Add("D");

// We need to rebind to the datasource on the post back since we are dynamically
// loading a user control.
Repeater1.DataSource = theData;
Repeater1.DataBind();

base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e)
{
}

void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
WebUserControl webUserControl = (WebUserControl)LoadControl(@"~\WebUserControl.ascx");
e.Item.Controls.Add(webUserControl);
}
protected void Button1_Click(object sender, EventArgs e)
{

}
}

I have a problem that I have boiled down to a very simple example.

I have a user control that displays a some data from a business object. On one screen I have a collection of these business objects and wish to display the user control multiple times. On this web page I simply bind the repeater to the data source and in the ItemDataBound event dynamically load the user control via "LoadControl()".

The user control contains an auto post back textbox. When the text in the textbox changes it is to update the database. (It is also to update the web page with the results of a calculation and thus the reason for the update on the _TextChange rather than updating on a submit button.)

The problem occurs when there are multiple user controls on the screen. The user can edit the textbox in a user control, the auto post back fires, the _TextChanged event is called and the database is updated. If the user were to then edit another textbox in another user control then not only does its _TextChange event get called but the first _TextChange event is raised again.

This means that if the user were to edit 9 user controls, then when the 10th is edited, 10 _TextChange events would be raised.

The _TextChange event sets of sophisticated chain of events. It should be raised only when required.

I have no idea why this is happening and no idea about how to solve it.

The code can be downloaded from www.tcpiq.com/temp/UserControlEvents.zip

The web page's source is

<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server">
</asp:Repeater>
</div>
</form>
</body>

and the code behind is

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Repeater1.ItemDataBound += new RepeaterItemEventHandler(Repeater1_ItemDataBound);

List<string> theData = new List<string>();
theData.Add("A");
theData.Add("B");
theData.Add("C");
theData.Add("D");

Repeater1.DataSource = theData;
Repeater1.DataBind();
}

void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
WebUserControl webUserControl = (WebUserControl)LoadControl(@"~\WebUserControl.ascx");
e.Item.Controls.Add(webUserControl);
}
}

The user control's source is

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" OnTextChanged="TextBox1_TextChanged"></asp:TextBox>

and the code behind is:

using System;

public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}

public void TextBox1_TextChanged(object sender, EventArgs e)
{
Response.Write(DateTime.Now.ToString() + " " + ((System.Web.UI.WebControls.TextBox) sender).ClientID.ToString() + " Text changed<br>");
}
}


Thanks in advance.

Dave A
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top