I'm having some trouble creating triggers for items inside of a repeater. I would like a Linkbutton control to trigger a postback from within an update panel, I have a trigger defined in markup for a Button control which works fine:
<Triggers>
<asp:PostBackTrigger ControlID="button" />
</Triggers>
However, I can't do this for the LinkButtons as they're created dynamically, only solution would be to add a trigger for each button in my repeaters data bound event like so:
//Inside repeater itemdatabound...
var trigger = new PostBackTrigger();
trigger.ControlID = linkButton.UniqueID;
updatepanel.Triggers.Add(trigger);
When running this code I receive an error:
A control with ID 'ctl00$content$repeater$ctl01$linkButton' could not be found for the trigger in UpdatePanel 'updatepanel'.
How can I dynamically add triggers for each of my LinkButtons?
Solved this. I'm assuming the reason that it didn't work in my OP is because the repeater controls aren't directly visible to the update panel.
I suspect moving them outside of the repeater would have solved it or making a tweak to the FindControl("linkbutton") call to drill down into the repeater for the control, using this method would mean that I need to create two link button objects for each level which is undesirable.
However, I think the cleaner solution is to register the LinkButton controls as postback controls using the scriptmanager:
//Create triggers for each 'remove' button
ScriptManager scriptManager = ScriptManager.GetCurrent(Page);
if (scriptManager != null)
{
scriptManager .RegisterPostBackControl(linkbutton);
}
Within the repeaters OnItemDataBound event, solved it.
I seem to recall that you can use the clientID rather than the uniqueID property for this.
Neat solution would be:
protected void MyRepeater_OnItemCreated(object sender, RepeaterItemEventArgs e)
{
//Inside ItemCreatedEvent
ScriptManager scriptMan = ScriptManager.GetCurrent(this);
LinkButton btn = e.Item.FindControl("btnSubmit") as LinkButton;
if (btn != null)
{
btn.Click += btnSubmit_Click;
scriptMan.RegisterAsyncPostBackControl(btn);
}
}
This is the source thread
Related
I am dynamically adding a RadioButtonList in the Code Behind. I want it so that the 'OnClick' does not call JavaScript, but instead it calls a method in my code behind.
Is this possible?
In addition, is there a way to set it up so that this say control has runat="server"?
You can use the Button Click Event
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.click(v=vs.110).aspx
Yes, it is possible. Also, there is no need to have runat="server" since your are creating the control in code.
You need to set your RadioButtonList object's OnSelectedIndexChanged event. As #Robert mentioned, if you are creating controls dynamically you need to wrap them in the Page_Init().
protected void Page_Init(Object sender, EventArgs e) {
RadioButtonList radiobuttonlist = new RadioButtonList();
radiobuttonlist.SelectedIndexChanged += radiobuttonList_CheckedChanged;
//Set the AutoPostBack to true proptery to that the user action
// will immediately post-back to the server
radiobuttonlist.AutoPostBack = true;
}
private void radiobuttonList_CheckedChanged(object sender, EventArgs e) {
//Code you want to execut when a user selects a different item
}
Reference: https://msdn.microsoft.com/en-us/library/System.Web.UI.WebControls.ListControl.SelectedIndexChanged(v=VS.110).aspx
Be sure to add the control in the Page_Init() portion of the code, not in Page_Load() or later. Set up the event handler += line inside the Page_Init() setup. The control should run server side if you do this. I'm not sure if runat="server" will be explicitly set but the control will behave that way.
I have a user control with a DropDownList with AutoPostBack = true, also I have an aspx page to display this control.
I re-create user control in OnInit method of the page
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var list = (List<Control>)Session[Controls];
if (list != null)
{
foreach (var control in list)
{
var uc = (Control)LoadControl(ControlPath);
uc.SetDropDownState(control.state);
PlaceHolderQuestion.Controls.Add(uc);
}
}
}
So while re-creating I am restoring DropDown selection, it works for the first time, but when I change selection again, OnSelectedIndexChanged event does not fire and it is obvious because I first restore DropDown selection in OnInit and so no OnSelectedIndexChanged event, cause nothing was changed, can you suggest some workaround?
UPDATE
var uc = (Control)LoadControl(ControlPath);
is required to be keep user controls events
After a deep research, I figured out that the issue was in the SelectedIndexChanged event logic.
I am using "Indirect Subscription" approach to handle it within my Page logic,
for more info please take a look
Indirect Subscription Approach
Originally I was reloading controls inside the handler but it was not required since I am doing it in the Page_Load method as well, so all I need to do is to update control inside my PlaceHolder controls list.
I hope it is clear, if not, please ask, and I will provide more description.
I'm using asp.net and c# for webForm. I'm generating a dropDownList dynamically, but I can't execute an event for this control. Below some code:
DropDownList nuevoCmb = new DropDownList();
nuevoCmb.ID = "ddl" + num;
nuevoCmb.Items.Add("---Seleccione el Plazo---");
nuevoCmb.Items.Add("Corto Plazo");
nuevoCmb.SelectedIndex = 0;
nuevoCmb.AutoPostBack = true;
nuevoCmb.SelectedIndexChanged += new EventHandler(nuevoCmb_OnSelectedIndexChanged);
MainPanel.Controls.Add(nuevoCmb);
protected void nuevoCmb_OnSelectedIndexChanged(object sender, EventArgs e)
{
string temp = "";
}
You need to add the code that creates the control to every page request, including postbacks. If the control causes a postback and the code that recreates the control is not called, your event handler will not fire. .NET will eventually call your event handler once a control with the same ID is added during the page load.
You should add dynamically added controls in or before the page Init event. It also works if you add during page Load event. After the Load event, your custom control events bubble up and fire. So if you're adding controls dynamically, they have to be added on each post back, being loaded before the page Load event ends, at the latest.
I found an answer in the follow page: Creating Dynamic DropDownList Controls in ASP.Net
This example is fully functional, but only an asp html page, is not working using master page. Any suggestion!
I have a repeater control where in the footer I have a DropDownList. In my code-behind I have:
protected void ddMyRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
|| e.Item.ItemType == ListItemType.AlternatingItem)
{
// Item binding code
}
else if (e.Item.ItemType == ListItemType.Footer)
{
DropDownList ddl = e.Item.FindDropDownList("ddMyDropDownList");
// Fill the list control
ddl.SelectedIndexChanged += new
EventHandler(ddMyDropDownList_SelectedIndexChanged);
ddl.AutoPostBack = true;
}
}
The page appear to PostBack however my EventHandler does not get called. Any ideas?
If you just want to fire the OnSelectedIndexChanged, this is how it should look:
Page.aspx - Source
<FooterTemplate>
<asp:DropDownList ID="ddlOptions"
runat="server"
AutoPostBack="true"
onselectedindexchanged="ddlOptions_SelectedIndexChanged">
<asp:ListItem>Option1</asp:ListItem>
<asp:ListItem>Option2</asp:ListItem>
</asp:DropDownList>
</FooterTemplate>
Page.aspx.cs - Code-behind
protected void ddlOptions_SelectedIndexChanged(object sender, EventArgs e)
{
//Event Code here.
}
And that's it. Nothing more is needed.
If the DropDownList is within a Repeater then to make the SelectIndexChanged event fire, you need to disable EnableViewState on the GridView / Repeater.
e.g.
EnableViewState="false"
You also need to databind the GridView / Repeater on each postback so databind it in the Page Load method.
I think it's because you're probably not databinding on postbacks. I haven't tested this, but try hooking that code up to the ItemCreated event for your repeater instead.
I think the problem comes from the fact that the dropdownlist control is not inside the repeter, but on the footer. I don't think that the envent of the reperter fires for the controls that are on the footer. You should try to put the dropdowncontrol out of the repeater control.
Is the AutoPostBack property set to True on the DropDownLists on the ASPX side? I know sometimes this property doesn't get set initially and it will prevent the SelectedIndexChanged event from firing.
In this case your parent repeater (ddMyRepeater) must databind itself in page_load on every postback. This is the only way I've found to get nested controls to fire their events.
This may not be the ideal scenario for you, though. Depending on what your page is doing, you may have to databind this control, twice. Once to get the events to fire and a second time if a fired event causes the repeater's data to change in any way.
Make sure ViewState is enabled for dropdownlist
I've got a Sharepoint WebPart which loads a custom User Control. The user control contains a Repeater which in turn contains several LinkButtons.
In the RenderContent call in the Webpart I've got some code to add event handlers:
ArrayList nextPages = new ArrayList();
//populate nextPages ....
AfterPageRepeater.DataSource = nextPages;
AfterPageRepeater.DataBind();
foreach (Control oRepeaterControl in AfterPageRepeater.Controls)
{
if (oRepeaterControl is RepeaterItem)
{
if (oRepeaterControl.HasControls())
{
foreach (Control oControl in oRepeaterControl.Controls)
{
if (oControl is LinkButton)
{
((LinkButton)oControl).Click += new EventHandler(PageNavigateButton_Click);
}
}
}
}
}
The function PageNavigateButton_Click is never called however. I can see it being added as an event handler in the debugger however.
Any ideas? I'm stumped how to do this.
By the time RenderContent() is called, all the registered event handlers have been called by the framework. You need to add the event handlers in an earlier method, like OnLoad():
protected override void OnLoad(EventArge e)
{ base.OnLoad(e);
EnsureChildControls();
var linkButtons = from c in AfterPageRepeater.Controls
.OfType<RepeaterItem>()
where c.HasControls()
select c into ris
from lb in ris.OfType<LinkButton>()
select lb;
foreach(var linkButton in linkButtons)
{ linkButton.Click += PageNavigateButton_Click
}
}
Have you tried assigning the CommandName and CommandArgument properties to each button as you iterate through? The Repeater control supports the ItemCommand event, which is an event that will be raised when a control with the CommandName property is hit.
From there it is easy enough to process because the CommandName and CommandArgument values are passed into the event and are readily accessible.
You need to make sure that the link button is re-added to the control tree and/or that the event is rewired up to the control before the event fires.
Article # 4guysfromrolla
I've never done a SharePoint WebPart, so I don't know if this will apply. But if it were a plain-old apsx page, I'd say that by the time it's rendering, it's too late. Try adding the event handlers in the control's Init or PreInit events.
Edit: Wait, I think Dilli-O might be right. See the Adding Button Controls to a Repeater section at the end of http://www.ondotnet.com/pub/a/dotnet/2003/03/03/repeater.html. It's in VB.NET, but you can easily do the same thing in C#.
As others have pointed out, you're adding the event handler too late in the page life cycle. For SharePoint WebParts you'd typically want to override the class' OnInit/CreateChildControls methods to handle the activity.
YOu need your webpart to implement the INamingContainer marker interface, it is used by the framework to allow postbacks to return to the correct control...
Also the controls in your webpart all need to have an ID.