Linking events from controls, when the controls have been created


G

Guest

I've a situation where I'm creating controls programatically. I'm
programatically creating table cells and rows. I've got an array of data,
and I want to format the data on screen in rows of 4. I get my array,
calculate how many complete rows I need. Then for each of the complete rows,
I format a cell for the data in that array element. When I've completed a
row, I add it to my table. If I have a remainder, I do that at the end.

This works very well. However, I want users to be able to select one of the
images I'm showing by clicking on it. Normally, I would do this by
<asp:Image ID="myImage" runat="server" OnClick="myImage_Click"/>
and I would put the code into
protected void myImageClick(object sender, EventArgs e)
{
Code Here
}

However, because I'm creating the ImageButton controls programatically, I
can't quite get an event wired in. I've created event handlers, but I think
that because each ImageButton class in created in FormatCell, then they are
out of scope in a postback. Does anyone have a way for me to reliably wire
an event handler into a programatically created control?




The code is below

protected void Page_Load(object sender, EventArgs e)
{
int typesPerRow = 4;
if (!IsPostBack)
{

PointType[] types = PointSystem.GetPointTypes();
TableRow tr;

//Display the point types, four in a row.
int rows = types.Length / typesPerRow;
int remainder = types.Length % typesPerRow;
for (int i = 0; i < rows; i++)
{
tr = new TableRow();
for (int j = 0; j < typesPerRow; j++)
{
tr.Cells.Add(FormatCell(types[counter]));
}
emailPointTable.Rows.Add(tr);
}

//Do the last (partial) row
if (remainder != 0)
{
tr = new TableRow();
for (int j = 0; j < remainder; j++)
{
tr.Cells.Add(FormatCell(types[counter]));
}
emailPointTable.Rows.Add(tr);
}
}


private TableCell FormatCell(PointType t)
{
ImageButtton pointPic;
TableCell cell;
LinkButton selectme;

cell = new TableCell();
cell.SkinID = "skinCell";

pointPic = new ImageButton();
pointPic.Click += new ImageClickEventHandler(this.pointTypeSelected);
pointPic.SkinID = "skinImage";
pointPic.ImageUrl = t.ImageLarge;
pointPic.Height = 128;
pointPic.Width = 128;

selectme = new LinkButton();
selectme.Text = t.Name;
selectme.CommandName = "SelectPointType";

cell.Controls.Add(pointPic);
cell.Controls.Add(new LiteralControl("<br/>"));
cell.Controls.Add(selectme);

return cell;
}
 
Ad

Advertisements

B

bruce barker

when you create the control just add the handler

myImage.OnClick += new ImageClickEventHandler(myImageClick);

to get the postback event, you need to recreate the controls (with the
same id's) in OnInit and assign the handlers


-- bruce (sqlwork.com)
 
P

Peter Bucher [MVP]

Hi rival
However, because I'm creating the ImageButton controls programatically, I
can't quite get an event wired in. I've created event handlers, but I
think
that because each ImageButton class in created in FormatCell, then they
are
out of scope in a postback. Does anyone have a way for me to reliably
wire
an event handler into a programatically created control?
you have to execute your code on every time, postback or not.
that means, place your code outside of if(!this.IsPostBack), then that
should work fine.
 
Ad

Advertisements

G

Guest

Thanks for this - firstly, Bruce - I'd already got the event linked in as you
described. "you need to recreate the controls (with the
same id's) in OnInit and assign the handlers" was the issue. I didn't want
to do a hundred object declarations in case I need the object! I think you
are driving at the same thing Peter has written below.
"you have to execute your code on every time, postback or not"

I've changed my Page_Load to this:
if (!IsPostBack)
{
emailPointTable.Visible = true;
}
else
{
emailPointTable.Visible = false;
}
PointType[] types = PointSystem.GetPointTypes();
TableRow tr;

//Display the point types, three in a row.
int rows = types.Length / typesPerRow;
int remainder = types.Length % typesPerRow;
int counter = 0;
for (int i = 0; i < rows; i++)
{
tr = new TableRow();
for (int j = 0; j < typesPerRow; j++)
{
tr.Cells.Add(FormatCell(types[counter]));
counter++;
}
emailPointTable.Rows.Add(tr);
}

//Do the last (partial) row
if (remainder != 0)
{
tr = new TableRow();
for (int j = 0; j < remainder; j++)
{
tr.Cells.Add(FormatCell(types[counter]));
counter++;
}
emailPointTable.Rows.Add(tr);
}

So if I'm posting back, I just don't render the table. And it works!
Fantastic help from both Bruce and Peter

Thanks again
 

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