Dynamically Loaded ListButton's and PostBack Event - asp.net

I am trying to get a dynamically loaded LinkButton to fire a postback event, which I then handle.
I have across Command, CommandName and CommandArgument - which looked real useful.. So I started messing with that, but currently cannot get to work as desired.
The links are rendered within a table that is created on the fly, here is the code to generate them:
// The links are stored in Session since I was told that the objects need to remain intact across requests.
LinkButton GetEditCardLink(string card)
{
if (!IsPostBack)
{
TW("Creating Link for Card '" + card + "' and Placing in Session.", true);
LinkButton link = CreateEditLink(card);
Business.Session.Set<LinkButton>("LinkedCards_EditLink_" + card, link);
}
return Business.Session.Get<LinkButton>("LinkedCards_EditLink_" + card);
}
// Here the link itself is created, note the ID and Command details are set.
LinkButton CreateEditLink(string forCard)
{
TW("Setting Up Link for Card: " + forCard, true);
LinkButton rtn = new LinkButton();
rtn.ID = "Edit_" + forCard;
rtn.Text = Resources.Header("EditDetails");
rtn.CommandName = "Edit";
rtn.CommandArgument = forCard;
rtn.Command += new CommandEventHandler(RedirectToEdit);
rtn.Attributes["style"] = "display: block; text-align:center;";
return rtn;
}
// ... And the delegate I want called on PostBack..
void RedirectToEdit(object sender, CommandEventArgs e)
{
TW("RedirectToEdit Called:\r\nName: " + e.CommandName + "\r\nArgument: " + e.CommandArgument);
}
Trace confirms that the LinkButtons are being loaded correctly, and are only being creating once, so in theory they should be fine, but when I click the link, a PostBack is performed, but the RedirectToEdit method is not called?
All help gratefully received! :)
NOTE
Oh, I thought I should mention TW is just a utility method for Trace.Write/Warn :)

When you create a control that needs event handling you have to do it early enough in the processing that the event handler gets hooked up. Override OnInit for the page where you are creating the table and move the table creation code there. As #ScarletGarden suggests, you also need to add the control whether it's a PostBack or not. I believe that doing it in Page_Load is too late for the event to be detected if you add the control there.
Reference

Here is my trial, and it worked :
protected void Page_Load(object sender, EventArgs e)
{
//if (!IsPostBack)
//{
placeHolderAtPage.Controls.Add(CreateEditLink("forCard1"));
//}
}
LinkButton CreateEditLink(string forCard)
{
LinkButton rtn = new LinkButton();
rtn.ID = "Edit_" + forCard;
rtn.Text = "EditDetails";
rtn.CommandName = "Edit";
rtn.CommandArgument = forCard;
rtn.Command += new CommandEventHandler(RedirectToEdit);
rtn.Attributes["style"] = "display: block; text-align:center;";
return rtn;
}
void RedirectToEdit(object sender, CommandEventArgs e)
{
Response.Write("RedirectToEdit Called:\r\nName: " + e.CommandName + "\r\nArgument: " + e.CommandArgument);
}
If you decomment the IsPostBack line, RedirectToEdit will be useless.
Only binding codes can be under IsPostBack control.

Related

Programmatically changing aspx button Click event on the Form Page_Load inconsistency

I'm getting an inconsistent behavior. I need to change the User Control's button Click event. I have two buttons, all the changes I make to the controls work fine, but there is only one Click event that doesn't change :
((Button)EntryControl.FindControl("CancelConfirmation").FindControl("btnYesCancel")).Click += new EventHandler(btnYesCancelTrade_Click);
all the other changes work just fine:
protected void Page_Load(object sender, EventArgs e)
{
((Label)EntryControl.FindControl("lbPurchaseDate")).Visible = false;
((TextBox)EntryControl.FindControl("txPurchaseDate")).Visible = false;
((Label)EntryControl.FindControl("lbPurchasePrice")).Visible = false;
((TextBox)EntryControl.FindControl("txPurchasePrice")).Visible = false;
((Button)EntryControl.FindControl("CancelConfirmation").FindControl("btnNoCancel")).Click += new EventHandler(btnNoCancelTrade_Click);
/*does not work*/ ((Button)EntryControl.FindControl("CancelConfirmation").FindControl("btnYesCancel")).Click += new EventHandler(btnYesCancelTrade_Click);
((Button)EntryControl.FindControl("CancelConfirmation").FindControl("btnYesCancel")).Text = "Yes Test";
}
am I missing something?
I was missing that I had to deregister the original handlers.

Page_PreLoad() event is triggered before link button click event when I click on a link button

I'm listing folders and files in drive E, I'm using a hidden field to keep the path, I created some link buttons representing folders, they are created programmatically on Page_PreLoad() event:
protected void Page_PreLoad(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(hdfPath.Value))
{
path = "E:\\" + hdfPath.Value;
directories = Directory.GetDirectories(path);
files = Directory.GetFiles(path);
}
else
{
directories = Directory.GetDirectories("E:\\");
files = Directory.GetFiles("E:\\");
}
for (int i = 0; i < directories.Length; i++)
{
LinkButton lkbLink = new LinkButton();
lkbLink.Click += new EventHandler(btn_Click);
void btn_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(hdfPath.Value))
hdfPath.Value = folderName;
else
hdfPath.Value += "\\" + folderName;
}
}
}
When I click in whichever link button, first of all Page_PreLoad() event is triggered then btn_Click() event, while I expected btn_Click() to be fired first. In that case the related value on hidden field belongs to the value of one step before.
Is something wrong with the ASP.Net life cycle I chose?
How can I make it immediately set the hidden filed value when user clicks on the link button so that the (correct) current value on hidden field be taken?
There is nothing wrong with the lifecycle and you can not choose a lifecycle either :)
The PreLoad-Event of the page is always before the control-events.
This will give you a detailed overview over the lifecycle in asp.net.
It's a little complicated in your case:
you need to add some buttons dynamically and attach event handlers to them - this has to be done on every postback, else the button-handlers won't be triggered.
Then in your handler you need to delete these before added buttons again and add the new ones according to the new path.
To achieve this, make a method from your code, e.g:
private void InitButtons()
{
if (!string.IsNullOrEmpty(hdfPath.Value))
{
path = "E:\\" + hdfPath.Value;
directories = Directory.GetDirectories(path);
files = Directory.GetFiles(path);
}
else
{
directories = Directory.GetDirectories("E:\\");
files = Directory.GetFiles("E:\\");
}
for (int i = 0; i < directories.Length; i++)
{
LinkButton lkbLink = new LinkButton();
lkbLink.Click += new EventHandler(btn_Click);
void btn_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(hdfPath.Value))
hdfPath.Value = folderName;
else
hdfPath.Value += "\\" + folderName;
// remove the old buttons here, if you need to
// RemoveOldButtons();
// call the Init-Buttons-Function again
InitButtons();
}
}
}
Call this method from your button event-handlers as shown above and again in your load-event-handler:
protected void Page_PreLoad(object sender, EventArgs e)
{
InitButtons();
}

How can I delete a dynamical control from an UpdatePanel at the click of a button?

I have an ASP.NET UpdatePanel where I add other panels dynamically. Each of these smaller panels has their own "Delete" Button.
When I click on one of those "Delete" button, I want the corresponding panel to be deleted. Instead, what happens is: I press "Delete", nothing happens, then when I do another operation that causes a PostBack, the panel is deleted. (Too late)
I draw every dynamical control on PostBack and when I click the Delete button, its handler (which deletes the panel I want) only occurs after I draw every control, so I don't see any changes immediately.
Here's the code that is called on every postback:
private void drawForm()
{
if (Session["controls"] != null)
{
PlaceHolder1.Controls.Clear();
Ccontrols = (Dictionary<Label, Control>)Session["controls"];
int index = 1;
foreach (var entry in Ccontrols)
{
Panel cPanel = new Panel();
cPanel.CssClass = "controldiv";
cPanel.ID = "cpanel" + index;
Button closebtn = new Button();
closebtn.Text = "Delete";
closebtn.ID = "closebtn" + index++;
closebtn.Click += new EventHandler(closeControl);
cPanel.Controls.Add(entry.Key);
cPanel.Controls.Add(entry.Value);
cPanel.Controls.Add(closebtn);
cPanel.Controls.Add(new LiteralControl("<br />"));
cPanel.Controls.Add(new LiteralControl("<br />"));
closebtn.CssClass = "closebutton";
PlaceHolder1.Controls.Add(cPanel);
}
FormPanel.Update();
}
else
{
FormPanel.ContentTemplateContainer.Controls.Clear();
}
Here is the DeleteButton handler:
private void closeControl(object sender, EventArgs e)
{
String id = (sender as Button).ID;
PlaceHolder1.Controls.Remove(PlaceHolder1.FindControl("cpanel" + id));
foreach (Control c in (sender as Button).Parent.Controls)
{
if (c is Label)
{
Ccontrols.Remove((Label)c);
}
}
Session["controls"] = Ccontrols;
drawForm();
}
Thanks in advance
I think there is some problem with your triggers in UpdatePanel.
I would be able to help you better if you would post your html code where you have created your UpdatePanel.

datalist custom paging in asp.net

I am doing custom paging for a datalist.Below method gets the required page numbers.
My problem is the click event is not being fired during debug.
Can anyone tel where the problem is.
private void BindPageNumbers(int TotalRecords)
{
int counter = 0;
for(int i=0;i<TotalRecords;i=i+5)
{
counter=counter+1;
LinkButton lnk = new LinkButton();
lnk.Click += new EventHandler(lbl_click);
lnk.ID = "lnkPage" + (counter).ToString();
lnk.Text = (counter).ToString();
pages.Controls.Add(lnk);
Label spacer = new Label();
spacer.Text = " ";
pages.Controls.Add(spacer);
}
}
void lbl_click(object sender, EventArgs e)
{
LinkButton lnk = sender as LinkButton;
int Currentpage = int.Parse(lnk.Text);
ListDataBinding_paging(2, this.Days, (Currentpage-1)*5, 5);
}
Here "ListDataBinding_paging" is the method from where the datalist is being filled.
You are creating your page link buttons dynamically. So they need to be re-created in every post-back early in the life-cycle. I suspect that BindPageNumbers is getting called after the post event data is processed and hence the click event does not get generated.
I suggest you to invoke BindPageNumbers in page_load for creating your buttons early in the life cycle. You can store the total records count in the view-state. If page_load doesn't help then try LoadViewState override - put the code after call to base implementation - something like
protected override void LoadViewState(Object savedState)
{
base.LoadViewState(savedState);
BindPageNumbers((int)ViewState["TotalRecords"]);
}

Adding ImageButton Programmatically

I have a code snippet like below and I want to add imagebuttons into my asp:Panel during page load. But the events are firing already when I run the page. I want it to be fired when it is clicked.
Thanks in advance for all helps
protected void Page_Load(object sender, EventArgs e)
{...
foreach (Gift g in bonusGifts)
{
ImageButton ib = new ImageButton();
ib.ImageUrl = g.GiftBanner;
ib.ID = g.GiftID.ToString();
ib.Click += Purchase(g);
BonusGiftPanel.Controls.Add(ib);
}
}
private ImageClickEventHandler Purchase(Gift g)
{
_giftRep.Purchase(g, _userSession.CurrentUser);
lblGifts.Text = "You have purcased " + g.GiftName + " for " + g.BonusPoints;
return null;
}
Add controls in your Page_Init, not in your Page_Load. [1]
Furthermore, you are not doing this the way it should. Consider this code
//your collection of objects goes here. It might be something different than
//this, but basically a Dictionary<int, YourType> goes fine
public Dictionary<Int32, string> Ids
{
get { return (ViewState["ids"] ?? new Dictionary<Int32, string>()) as Dictionary<Int32, string>; }
set { ViewState["ids"] = new Dictionary<Int32, string>(); }
}
protected void Page_Init(object sender, EventArgs e)
{
//load the data using your DAO
Ids = new Dictionary<int, string>();
Ids.Add(1, "http://www.huddletogether.com/projects/lightbox2/images/image-2.jpg");
Ids.Add(2, "http://helios.gsfc.nasa.gov/image_euv_press.jpg");
foreach (var item in Ids)
{
ImageButton imb = new ImageButton()
{
ImageUrl = item.Value,
CommandArgument = item.Key.ToString(),
CommandName = "open"
};
imb.Click += new ImageClickEventHandler(imb_Click);
PH1.Controls.Add(imb);
}
}
void imb_Click(object sender, ImageClickEventArgs e)
{
Response.Write("You purchased " + Ids[int.Parse(((ImageButton)sender).CommandArgument)]);
}
[1] (CTRL+C/CTRL+V from some other question I answered last week):
Everything that has to be maintained between page cycles should be declared in Page_Init, not Page_Load.
All the initialization, like adding event handlers, and adding controls should be added during initialization, as the state is saved between page cycles. Handling with the content of controls and the viewstate, should be done in Load.
Check also http://msdn.microsoft.com/en-us/library/ms178472.aspx.
Init
Raised after all controls have been initialized and any skin
settings have been applied. Use this
event to read or initialize control
properties.
.
Load
The Page calls the OnLoad event method
on the Page, then recursively does the
same for each child control, which
does the same for each of its child
controls until the page and all
controls are loaded.
Use the OnLoad event method to set
properties in controls and establish
database connections.
You should add the controls in the Page Init event, as other have said.
Your image click event handler does not conform to the ImageButton Click event handler signature. That should look something like this:
private void ImageButton_Click(ByVal sender As Object, ByVal e As ImageClickEventArgs)
{
}
Note that you can't pass your "Gift" object directly to the ImageButton_Click. You will have to find another method of doing that.
You need to take a look at the Page Lifecycle - http://msdn.microsoft.com/en-us/library/ms178472.aspx

Resources