Hosting page:
protected void Page_Load(object sender, EventArgs e)
{
LoadMyControl(Parameters); //Do it every page load to preserve it's state
}
protected void LoadMyControl(string parameters)
{
plchld.Controls.Clear();
Control userControl = LoadControl("TheUserControl.ascx");
userControl.ID = "userControl1";
plchld.Controls.Add(userControl);
}
Now inside this control, when a button is clicked I want to update ,let's say a Label on the hosting page.
What is the best way to do it? Custom event?
Solution maybe:
In the parent page add:
public Label Actions
{
get { return _Actions; }
set { _Actions = value; }
}
on User Control add the following to the top
<%# Reference Page="../parentpage.aspx" %>
and to change the value just do the following in the user control
ASP.parentpage cc = (ASP.parentpage)this.Parent.Page;
cc.Actions.Text = "hello world";
A UserControl has a Page property which is a reference to the page in which the control is added. You could either cast directly to the known page type that contains the label,
e.g.
protected void Button1_Click(object sender, EventArgs e)
{
var page = Page as _Default;
if (page != null)
{
page.Label1.Text = "Hello World";
}
}
but what would probably be better, is that you decorate you pages where this control can be used with an interface:
public interface ILabelHost
{
void SetLabel(string text);
}
public class _Default : System.Web.UI.Page, ILabelHost
{
...
That way you can use that same logic from before, but on anypage the control is loaded and implements the correct interface:
protected void Button1_Click(object sender, EventArgs e)
{
var host = Page as ILabelHost;
if (host != null)
{
host.SetLabel("Hello World");
}
}
Related
I'm currently having two master pages M1 and M2 and several content pages.
M2 has a calendar control and I want to call a content page function each time the selection on the calendar changes.
Here's the code I have in my master page:
public partial class Master2 : BaseMasterPage
{
public event EventHandler CalendarSelectionChanged;
public void Calendar_OnSelectionChanged(object sender, EventArgs e)
{
if (CalendarSelectionChanged != null)
CalendarSelectionChanged(this, EventArgs.Empty);
}
}
And here's the code in the content Page C1:
protected void Page_PreInit(object sender, EventArgs e)
{
Master.CalendarSelectionChanged += new EventHandler(OnMainCalendarSelectionChanged_SubContent);
}
private void OnMainCalendarSelectionChanged_SubContent(object sender, EventArgs e)
{
DoSomething();
}
but the CalendarSelectionChanged is always null and hence the function isn't called.
After some serious researching and dabbling around, I've finally made the calendar in the Master page to trigger an event in the content page.
The Code in the Content Page is the same as mentioned in the question.
The Code in the Second Master page(Nested) is Changed to :
public partial class Master2 : BaseMasterPage
{
public event EventHandler CalendarSelectionChanged;
public void Calendar_OnSelectionChanged(object sender, EventArgs e)
{
OnCalendar_SelectionChanged_CustomEvent(e);
///.....
}
public virtual void OnCalendar_SelectionChanged_CustomEvent(EventArgs e)
{
if (Calendar_SelectionChanged_CustomEvent != null)
Calendar_SelectionChanged_CustomEvent(this, EventArgs.Empty);
}
}
Add the virtual reference path in the content page:
<%# MasterType VirtualPath="~/MasterPage.master" %>
I have having some trouble with communication from a usercontrol to the main page. The order in which events are raised means that the action on the user control occurs too late in the post back to have an effect on the main page.
For example, I have a button on a user control which, when pressed, raises a custom event that is being listened for on the main page. When the button is pressed the postback order is:
page_load - on the main page
page_load - on the usercontrol (the user control is loaded programitically by the main page page_load)
The button call back on the user control
The event call back method on the main page
By this point, it seems it is too late for anything the event call back method does to have any effect on the rendered page, for example I am trying to use it to change the usercontrol that is being displayed.
What other techniques can be used for this kind of communication?
Relevant code
Main page:
public string LastLoadedControl
{
get
{
return Session["LastLoaded"] as string;
}
set
{
Session["LastLoaded"] = value;
}
}
private void LoadUserControl()
{
string controlPath = LastLoadedControl;
ContentPlaceholder.Controls.Clear();
if (string.IsNullOrEmpty(controlPath))
controlPath = Utils.Paths.USERCTRL_BASE + "Main.ascx";
Control uc = Page.LoadControl(controlPath);
ContentPlaceholder.Controls.Add(uc);
}
protected void Page_Load(object sender, EventArgs e)
{
LoadUserControl();
if (!IsPostBack)
Utils.Events.redirectPage += Events_redirectPage;
}
private void Events_redirectPage(string path)
{
if (path.Equals("Main"))
{
//Session.Clear();
//Session.Abandon();
}
else LastLoadedControl = Paths.USERCTRL_BASE + path + ".ascx"
LoadUserControl();
}
User control
protected void profileBtn_Click(object sender, EventArgs e)
{
Utils.Events.triggerRedirectPage("Login");
}
Event
public class Events
{
public delegate void redirectEvent(string path);
public static event redirectEvent redirectPage;
public static void triggerRedirectPage(String path)
{
if (Utils.Events.redirectPage != null)
Utils.Events.redirectPage(path);
}
}
There are two approaches that you can follow.
Approach 1:
public interface IEventProvider
{
void TriggerEvent();
}
public class YourPage: Page, IEventProvider
{
// Other page methods
public void TriggerEvent()
{
// Your Implementation
}
}
public class YourUserControl : WebUserControl
{
protected void profileBtn_Click(object sender, EventArgs e)
{
IEventProvider eventProvider = this.Page as IEventProvider;
if(eventProvider != null)
eventProvider.TriggerEvent();
}
}
Approach 2:
public interface IEventProvider
{
// This does not have to be a boolean. You can use a string / enum / anything that suits your implementation
bool Trigger {get; set;}
}
public class YourPage: Page, IEventProvider
{
// Other page methods
protected override void OnLoadComplete(EventArgs e)
{
// This will be raised when all the events have fired for all the controls in the page.
if(this.Trigger)
TriggerEvent();
}
protected void TriggerEvent()
{
// Your code here
}
public bool Trigger
{
get;
set;
}
}
public class YourUserControl : WebUserControl
{
protected void profileBtn_Click(object sender, EventArgs e)
{
IEventProvider eventProvider = this.Page as IEventProvider;
if(eventProvider != null)
eventProvider.Trigger = true;
}
}
I'm trying to load usercontrols on button click, but problem is that, it disappears on postback inside user control.
this is how i load controls:
private bool IsUserControl
{
get
{
if (ViewState["IsUserControl"] != null)
{
return (bool)ViewState["IsUserControl"];
}
else
{
return false;
}
}
set
{
ViewState["IsUserControl"] = value;
}
}
#region Usercontrols
private void CreateUserControlAllNews()
{
Control featuredProduct = Page.LoadControl("path/usercontrol.ascx");
plh1.Controls.Add(featuredProduct);
}
#endregion
protected void allNewsbtn_Click(object sender, EventArgs e)
{
this.IsUserControl = true;
if(IsUserControl)
CreateUserControlAllNews();
}
You need to reload the control when the page is post back. For example,
protected void Page_Load(object sender, EventArgs e)
{
if (IsUserControl)
{
CreateUserControlAllNews();
}
}
private void CreateUserControlAllNews()
{
Control featuredProduct = Page.LoadControl("path/usercontrol.ascx");
featuredProduct.ID = "1234";
plh1.Controls.Add(featuredProduct);
}
OF course it disappears, every request creates a brand new instance of your page and if you dont re-create the control on that postback then it wont exist.
See the following links about this very common issue.
Singing eels
Another SO question
I have searched extensively on this, but cannot find the solution to my problem. I am trying to call a function in the code behind of a page from a user control on that page.
I have a web application that uses a master page. I am adding a user control that I wrote to one of the content pages. I added the user control to the aspx page by dragging and dropping it from the toolbox. I am able to see the user control from the code behind, but I cannot access the public functions. To fix that problem, I created an object of the user control in the code behind and used the LoadControl function. All of that seems to work fine.
The problem I am having is when I am trying to hook the into the EventHandler from the aspx page to the user control. Everything compiles and runs just fine, but I am not seeing anything happen on the page. I think the issue is that the EventHandler is always null.
User Control Code
public partial class ucBuyerList : System.Web.UI.UserControl
{
public delegate void BuyerSelectedEventHandler(object sender, EventArgs e);
public event BuyerSelectedEventHandler BuyerSelected;
private string name = "";
public string Name
{
get { return name; }
set { name = value; }
}
private string auid = "";
public string AUID
{
get { return auid; }
set { auid = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
private void OnBuyerSelected(EventArgs e)
{
if (BuyerSelected != null)
{
BuyerSelected(this, new EventArgs());
}
}
protected void lbBuyerList_SelectedIndexChanged(object sender, EventArgs e)
{
SetNameAndAUID();
OnBuyerSelected(e);
}
private void SetNameAndAUID()
{
name = lbBuyerList.SelectedItem.Text;
auid = lbBuyerList.SelectedItem.Value;
}
}
Parent Page Code
public partial class frmBuyerInformation : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Master.changePageTitle("Buyer Information");
buyerList.BuyerSelected += new ucBuyerList.BuyerSelectedEventHandler(buyerListControl_BuyerSelected);
}
void buyerListControl_BuyerSelected(object sender, EventArgs e)
{
DisplayBuyerInformation();
}
public void DisplayBuyerInformation()
{
tbName.Text = buyerList.Name;
tbAUID.Text = buyerList.AUID;
}
}
Can anyone see what I am doing wrong?
EDIT: This issue has been resolved. The code snippits above are now functional. If anyone runs into the issue I had, you can model the code above. Make sure that AutoEventWireup="true" in both the aspx and ascx pages. Thank you June Paik for your solution. Thank you Diego De Vita for your input as well.
I've been struggling with events for quite a while as well. Nowadays I always create them this way 'cause it's the only way I know it works. Haven't tested it with your code but here it goes anyway:
public partial class ucBuyerList : System.Web.UI.UserControl
{
public delegate void BuyerSelectedEventHandler(object sender, EventArgs e);
public event BuyerSelectedEventHandler BuyerSelected;
public string Name;
public string AUID;
protected void Page_Load(object sender, EventArgs e)
{
//Select the first buyer in the list when the user control loads
if (!IsPostBack)
{
lbBuyerList.SelectedIndex = 0;
}
}
private void OnBuyerSelected(EventArgs e)
{
BuyerSelectedEventHandler handler = BuyerSelected;
if (handler != null)
{
handler(this, new EventArgs());
}
}
protected void lbBuyerList_SelectedIndexChanged(object sender, EventArgs e)
{
Name = lbBuyerList.SelectedItem.Text;
AUID = lbBuyerList.SelectedItem.Value;
OnBuyerSelected(e);
}
}
In the parent page you can just call your function the same way you're doing it already.
It could be that Page_Load is too late in the page lifecycle to be using LoadControl and subscribing to the event. What happens if you move that code to the Page_Init method?
I have a User Control with with some search functionality, then I also have a control that contains a grid. In the control that has the grid I have all the functionality to retrieve some items I need to populate a report from the search control.
My question is, and I have read about this but not completely sure how to make it work, I read i need to register a event handler in control A that calls the function in control B. How does that work?
Say in control B there is a function that I need to call GetAllItemsByRegistrantID(int id). How can I make a call to this function from control A?
I would really appreciate any help or guidance on this.
Regards
Here is an example if you had to do it using events.
On your first user control (the search control) define a custom event.
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public event EventHandler<MyCustomeEventArgs> MyCustomClickEvent;
protected virtual void OnMyCustomClickEvent(MyCustomeEventArgs e)
{
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
public void button1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(new MyCustomeEventArgs(5));
}
}
public class MyCustomeEventArgs : EventArgs
{
public MyCustomeEventArgs(int searchID)
{
SearchID = searchID;
}
public int SearchID { get; set; }
}
On your user control with the grid, define a handler.
public void HandleCustomEvent(object sender, MyCustomeEventArgs e)
{
GetAllItemsByRegistrantID(e.SearchID);
}
public void GetAllItemsByRegistrantID(int id)
{
Label1.Text = id.ToString();
}
On the page where they both live, wire them together.
protected void Page_Load(object sender, EventArgs e)
{
UserControl1Instance.MyCustomClickEvent += UserControl2Instance.HandleCustomEvent;
}
I would definitely try and avoid this sort of situation. You should be putting this sort of code in a class and sharing this between the two controls.