How to set method to call of usercontrol link - c#

I've created a user control that displays the header (not < head >, I mean the title, datetime page is created and so on) on each page on my website. In that user control I also have one link. A link that will be displayed on the page IF (user = admin).
Currently this link is a pure link, and I have no problems to change the "navigateUrl" to the correct value for each page. (Each page includes this user control, and from each page I set the value for navigateUrl.)
But!
On some of my pages I use a linkbutton instead of a hyperlink. But then I have to add that linkbutton from the page.aspx instead of usercontrol.ascx
My problem is that, I want to change the hyperlink in my user control to a linkbutton instead, so I can call methods with that link. (Method is on page.aspx, not within the user control).
What method to call differ from page to page, so I want to set which method to call each time I include the user control.
If I have inside my user control
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
And for now I set values within the usercontrol by:
mainPageHeader1.headTitle = "text";
How do I set what method to call for the linkbutton?

Update
In the markup of your UserControl, specify the handler for the click event
<asp:LinkButton OnClick="LinkButton1_Clicked" runat="server" ID="LinkButton1" />
Declare a custom event in your usercontrol
public class MyUserControl
{
public event System.EventHandler LinkButtonClicked;
//add handler for your LinkButton
protected void LinkButton1_Clicked(object sender, EventArgs e)
{
//Raise your custom event here that can be handled in any page that use your control
LinkButtonClicked(sender, e);
}
}
In your page.aspx, add handler for your custom event
protected void MyUserControl2_LinkButtonClicked(object sender, EventArgs e)
{
//handle the event here
}
Update
In your page where you add your control,
<custom:MyUserControl ID="MyUserControl2" runat="server"
LinkButtonClicked="MyUserControl_LinkButtonClicked" />
That's all
Update
Subscribing for the event in code-behind did the work. I have not figured out why it didn't work from the markup.
From the Page_Load of the page in which the UserControl is, do this
MyUserControl2.LinkButtonClicked += new EventHandler(MyUserControl_LinkButtonClicked);
and it should work.
Checks to see if the event has been subscribed to Either codebehind (eventhandler += EventHandler(sender, e) or the aspx markup OnClick="EventHandlerMethodName") - this would be null if it wasn't subscribed to somewhere

Related

C# dynamically created user control button click not working

I have a page (company.aspx) that when you click a button on the page the button click event (btnShowDeptsUserControl_Click) dynamically creates a user control and adds to a placeholder. The page reloads with the user control displayed. That works fine.
The issue I am having is that when I click the button on the user control itself, the btnEmailDepts_Click event is not fired, but the main page (company.aspx) is reloaded.
I have read that one way to resolve this is to create the dynamic user control in Page_Init, but I am creating the user control from the main page button click. Also, I am not declaring the user control in the code behind of the main page as you would normally, but do have a placehoder within which the user control is added.
I have also read that you can add a delegate to the main page for the user control button click, but the example seemed to have so much necessary code for such a simple thing that I figured there must be a better way.
Here are the relevant code snippets:
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<asp:PlaceHolder ID="phUserControls" runat="server"></asp:PlaceHolder>
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
CreateDeptsUserControl();
}
private void CreateDeptsUserControl()
{
phUserControls.Controls.Clear();
var uc = (UserControl)LoadControl("~/controls/ucDepartments.ascx");
phUserControls.Controls.Add(uc);
}
ucDepartments.ascx:
<asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />
ucDepartments.ascx.cs:
protected void btnEmailDepts_Click(object sender, EventArgs e)
{
EmailDepts(); // breakpoint here is never hit
}
private void EmailDepts()
{
// do something
}
If you read the MSDN, you will notice:
However, the added control does not catch up with postback data processing. For an added control to participate in postback data processing, including validation, the control must be added in the Init event rather than in the Load event.
You are adding your control in the click event which happens after both init and load events, so the postback will not work.
You can call your CreateDeptsUserControl function in the ini event, but there you will have to detect if the btnShowDeptsUserControl was clicked by yourself. It's not hard, you will need to check the submitted values collection and see if there is an item for btnShowDeptsUserControl.
Just wanted to post what I did to make this work. Racil Hilan's answer helped me to arrive at this solution. I did away with the dynamic user control, and went with the more common declared user control in the aspx, but set it to Visible="False" by default.
Notice that the main page button event is empty. Also notice that the user control Page_Load event is empty. All the checking is done in the user control OnInit event, which is executed with each main page load.
In the user control OnInit event I have a couple guard conditions that check to see what EVENTTARGET, if any, caused the page / user control to load. If the EVENTTARGET (control ID) is that of the main page button, then execution will continue and will call LoadSomeData() as well as set the user control Visible = true. Otherwise, if either guard condition evaluates as false, we exit and the user control does not get loaded, so no wasted db / service calls.
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
// empty, just need the event for inspection later in user control OnInit event.
}
ucDepartments.ascx:
<asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />
ucDepartments.ascx.cs:
protected override void OnInit(EventArgs e)
{
if (string.IsNullOrWhiteSpace(Request.Params["__EVENTTARGET"]))
return;
var controlName = Request.Params["__EVENTTARGET"];
if (controlName != "btnShowDeptsUserControl")
return;
LoadSomeData(); // call method to load the user control
this.Visible = true;
}
protected void Page_Load(object sender, EventArgs e)
{
// empty
}
private void LoadSomeData()
{
// get data from database
// load table / gridview / etc
// make service call
}
protected void btnEmailDepts_Click(object sender, EventArgs e)
{
EmailDepts(); // this event is now executed when the button is clicked
}
private void EmailDepts()
{
// do something
}
Variation that includes jquery to scroll to user control after postback:
In the main page button click event you can also do something like set a hidden var to a value that can be inspected on main page doc ready to do some jquery stuff, such as scrolling the user control into view if it is far down the page (which I am actually doing in my current task).
Not only will this scroll the now loaded user control into view after clicking the main page button, but notice the code in setupDepts(). I hide the asp button that does a postback to load the user control, and show a regular html button. They both look the same (both say Show Depts), but the regular html button, when clicked, will fire jquery to toggle the div that contains the user control to close, click again, it will open, click again it will close, etc.
This is so that you only load the user control once (make db / service calls once) when the main page button is clicked, and then can toggle show or hide it with subsequent clicks of the alternate button. This approach can be used with multiple buttons or links so long as they all have the same class ids. For example, you may have a Show Depts button / link at top of page and another at the bottom of the page, which is the case in my current task.
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" class="btnShowDepts" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<button class="btnToggleDepts" style="display: none;">Show Depts</button>
<div id="divShowDepts" style="display: none;">
<asp:HiddenField runat="server" id="hdnShowDepts"/>
<uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
</div>
<script language="javascript" type="text/javascript">
$(function () {
toggleDeptsUserControl();
if ($('#<%=hdnShowDepts.ClientID%>').val() === "show")
setupDepts();
});
function setupDepts() {
$('.btnShowDeptsUserControl').hide();
$('.btnToggleDeptsUserControl').show();
scrollToDepts();
}
function scrollToDepts() {
$('#divShowDepts').toggle(700, function () {
if ($(this).is(":visible")) {
$('html, body').animate({ scrollTop: ($(this).offset().top) }, 'slow');
}
});
}
function toggleDeptsUserControl() {
$('.btnToggleDeptsUserControl').on('click', function (event) {
event.preventDefault();
scrollToDepts();
});
}
</script>
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
hdnShowDepts.Value = "show";
}

Button not firing in user control

I currently have a master page that has a drop down menu which displays a different User control depending on the menu choice.
Inside of the User control I'm trying to add a submit button that processes the inputted forms inside the user controls using the "_Click()" event handler. My user control aspx looks like the following:
<asp:Button ID="configBttn" runat="server" OnClick="configBttn_Click" AutoEventWireUp="true" />
and then I have the following in the codebehind:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void configBttn_Click(object sender, EventArgs e)
{
Response.Write("Hello world");
}
I have even tried to add an event handler:
configBttn.Click += new EventHandler(configBttn_Click)
However this is still not allowing for the button to be triggered. Any ideas?
I add the user control inside the codebehind inside a div container:
divContainer.Controls.Add(pPage.LoadControl("~/Controls/Control.ascx"));
Where are you creating the UserControl in the Page Lifecycle?
I suspect that it needs to be created in the Init method of its container page.
In addition, they should not be wrapped in a !IsPostback block, or else when the page posts back, the control event handler is not mapped, so nothing is there to catch the click event.
Without seeing the code that adds the user control, I'm guessing that it is not saved as part of the page's view state. Which means when you click the button inside the user control the whole page gets refreshed and the user control is either not created or a different instance of it is created.

How do I get my asp:Button to execute code in the OnClick event?

First off... I'm a noob to both ASP.net and C#. I'm updating a page that already exists to add a button..
My code..
<div style="padding: 10px;float: left;"><table><tr><td><asp:Button id="DoSomething" Text="Build Patch" runat="server" OnClick="DoSomething_click" /><br /></td></tr></table></div>
This lives in my ascx control... the code behind is...
protected void DoSomething_click(object sender, System.EventArgs e)
{
Response.Write("<script> alert('Hi');</script>");
}
It gets wired up on the default.aspx page in
<%# Register Src="~/ui/MyView.ascx" TagName="MyView" TagPrefix="UC" %>
and is used in a asp:repeater...
<UC:MyView PB=<%# Container.DataItem %> runat="server"></UC:MyView>
The repeater creates the buttons inside a <td>
I supose my question is how do I wire up the onclick for these buttons? I debug and my DoSomething_click method never hits.
Basically you need to pass your ButtonClick event from UserControl to your webpage ( that contains this userControl). This is known as Bubble up of events
User control portion:
Define your OnClick event for the Button. However, in this event you will pass this to your .aspx page.
public partial class MyView : System.Web.UI.UserControl
{
public event EventHandler SomethingButtonClick;
protected void DoSomething_Click(object sender, EventArgs e)
{
//pass the event up to the aspx page. also called bubbling up the event.
if (this.SomethingButtonClick != null)
this.SomethingButtonClick(this, e);
}
}
Your page containg the UserControl:
Set the event handler for SomethingButtonClick event in Page_Init() event as :
protected void Page_Init(object sender, EventArgs e)
{
MyView1.SomethingButtonClick += new EventHandler(MyView_SomethingButtonClick);
}
Add/Define this MyView_SomethingButtonClick in your page code behind itself.
protected void MyView_SomethingButtonClick(object sender, EventArgs e)
{
//handle the event
Response.Write("<script> alert('Hi');</script>");
}
First off, try specifying type="text/javascript" inside of your script tag:
<script type="text/javascript">alert('hi');</script>
Assuming that doesn't work:
If I understand correctly, you are trying to link the dynamically created button to the code in the codebehind. This can get very, very weird. I would recommend using a "proxy function" of sorts. Create a javascript function elsewhere on the page that gets called by the button(s)' click event. This javascript function can then initiate a postback from there. I'll see if I can find the example I've used elsewhere.
EDIT: I can't find my original example, but this is a good reference: ASP.NET postback with JavaScript
Please note that the __doPostBack() function has TWO underscores, not one.

Delegates, UpdatePanels and ascx controls

I have built an ascx control that is part of many different components of my application. There is a Previous and Next button on this control, which should be signaled to the parent aspx page. This is done by having the parent page add some Delegates for postbacks, such as OnPreviousClicked, OnNextClicked etc.
Everything in this app is 'ajaxified' with an updatepanel. Now I notice that my app breaks if I don't set the delegates on every single Page_Load call in the parent. In other words, if I don't ALWAYS set the delegates in the Page_Load of the parent aspx, then the ascx ends up with null delegates and an exception. Am I coding stuff correctly?
// inside the control
public event EventHandler OnPreviousClicked;
private void PreviousButton_OnClick(object sender, EventArgs e)
{
if(OnPreviousClicked != null) {
OnPreviousClicked(this, e); // or whatever args you want
}
}
// and inside the Page code-behind
private void Page_Load(...)
{
MyUserControl.OnPreviousClicked += new EventHandler(myHandler);
}
// OR inside the Page aspx, you also could just set the OnPreviousClicked property.
<xx:MyUserControl ID="MyUserControl1" runat="server" OnPreviousClicked="myHandler" />
See http://asp.net-tutorials.com/user-controls/events/.
If all you're doing is signaling the clicking of a button, I would have your ASCX control raise a simple event instead. That way each page can listen for the event if they need to and the controls can function regardless if anybody is listening.
First declare the events in your ASCX codebehind:
public event System.EventHandler NextSelected;
Then you create your button click events that raise the event.
protected void btnNextSelected_Click(object sender, EventArgs e)
{
if (EmployeeSelected != null)
{
NextSelected(this, new EventArgs());
}
}
Then in your parent ASP.Net pages you can add your ASCX control (we'll call it NavControl) and create methods that listen for these events.
NavControl.NextSelected += new EventHandler(NextPageRedirect);
protected void NextPageRedirect(object sender, EventArgs e)
{
Response.Redirect("~/ViewEmployee.aspx", false);
}
Note that with this you don't have to create the event handler or method and you can still use the nav control on your page. It should also eliminate the issues you are having with the delegates.
remember each postback has to restart your code. The event handlers don't get serialized to viewstate so you have to set them up again.
That is the expected behavior in asp.net.
The entire page life cycle occurs even when it is a partial postback (update panel). So in order for the events to fire, you will have to wire them up programmatically during page_load or declaratively in your markup (if those delegates you mentioned are events).

There has to be a way to get my data bound at the correct time

Say aspx page called theParent has a DataGrid control named theDataGrid and a UserControl named theUserControl , and theUserControl has a button named theUcButton .
Yes, I know, very imaginative naming.
When theUcButton is clicked , a session variable is changed.
This session variable is a select parameter for the datasource of theDataGrid.
However, because of the order of stuff called in the page lifecycle, when theUcButton is clicked and a postback is generated ,
theParent controls are loaded before theUserControl resets the session variable, and theDataGrid does not show the new data until the next postback .
How to I get what I want to work?
I am using 3.5 if that matters.
Here is example code for your user control to raise an event.
public partial class WebUserControl : System.Web.UI.UserControl{
public event EventHandler Updated;
protected void Button1_Click(object sender, EventArgs e)
{
//do some work to this user control
//raise the Updated event
if (Updated != null)
Updated(sender, e);
}}
Then from your .aspx page, you'll deal with the new event just like usual
<uc1:WebUserControl ID="WebUserControl1" runat="server" OnUpdated="WebUserControl1_Updated" />
Code behind:
protected void WebUserControl1_Updated(object sender, EventArgs e)
{
//handle the user control event
}
You can declare an event as a member of the UserControl class, raise it, and handle it in the Page class.
You can also use other events like Page.PreRender() to pick up things after the user control's events.
The easiest way would be to hold off on the databind until the later in the lifecycle, such as the Page.PreRender event as joelt suggested. If you do the bind then, you should have the session variables.

Categories

Resources