I'd like someone to give what we're doing a glance-over and tell me whether we're going about it an odd way.
What I have:
We have a .master (Master Page), .aspx (Content Page) and an .ascx (User Control).
The User Control should appear on all pages, so we have placed it on the Master Page
The User Control should be initialised differently based on the Content Page it appears on. So, the Content Page has the resposibility of raising an event on the User Control, passing in some arguments, which initialises the control.
Questions:
In my mind, this removes any dependency between the User Control and either the Content Page or Master Page. Am I correct?
Is calling an event on the User Control the easiest way to pass arguments in and initialise the control accordingly?
Happy to clarify any further points, Thanks.
I would say that's OK, but I would like to seek a clarification: how does the user control subscribe to the event of the content page?
Alternatively, you could also consider creating an interface for the master page:
public interface IMyMaster
{
UserControlType Control { get; }
}
After applying this interface to the master, the interface can return a direct reference to the control. The content page can then do:
if (this.Page.Master is IMyMaster) {
((IMyMaster)this.Page.Master).Control.Initialize();
}
HTH.
Related
I have the following case:
Page1.aspx this page has the master page master.aspx.
I have some code in the master page :
if (!Page.IsPostBack)
{
adjustServiceBar();
}
when i click any button in the Page1.aspxit enters the !Page.IsPostBack and execute the method !!
i want this method in the !Page.IsPostBack) only
One way to do this is to set a session variable and then check that variable to ensure your code will fire only once.
Another way is to set a hidden control on your form and play with its text or value property.
According to each scenario the solution may be very complex such as custom derived masterpages and pages that extend the current events functionality to suit your needs.
I believe it is more consistent to check for IsPostBack in content page. You can move this condition to Page1.aspx and expose adjustServiceBar() method in your master page, so that content pages can call it, like Master.adjustServiceBar().
The Scenario: I have an asp.net website where I show a div popup on page load for taking a few user details. When a user inputs the details, or closes the popup, I set up a flag cookie so that the popup is not displayed again for the user. The div is in the MasterPage so that it is displayed no matter on which page a user lands first time. The div contains an UpdatePanel which has all the controls required for taking the details. This whole functionality is working fine.
The Problem: Now this div popup is not showing(by setting display:none) on subsequent postbacks(which I want), but the html markup is still loading with the page unnecessarily adding to the page size. What I would idealy want to do is: Check if flag cookie is set. If no, show the popup, else remove the popup's markup from the page.
Now since the div is not a server control, I cannot possibly remove it and the all the controls inside it. So, I thought of removing the UpdatePanel from the page:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["flag"] != null)
{
if (Page.Controls.Contains(updpnl_contact))
{
Page.Controls.Remove(updpnl_contact);
updpnl_contact.Dispose();
}
}
}
But I guess this tends to work with dynamically added controls only, and since the control is added at Design Time, it is not being removed.
Is there any way I can achieve this?
If you add a runat="server" attribute to your <div> element, it will be available in the code-behind. You'll need an id on it as well. Then you can just toggle the Visible property. If this property is false, the control won't be rendered to the client (i.e. no HTML markup).
What you're trying to do is not at all the usual workflow. I tend to think that it will not work as it would mess up control tree, maybe even corrupt the viewstate and so on.
As a possible solution, you can put it's visibility to hidden in the code behind. This, in the contrary to the usual 'gut feeling', doesn't work like the css propery 'display:none' for example - instead the control will not even be rendered into the page when it's not visible. This may be the workaround for you.
Happy coding.
A more efficient approach would be to create the panel as a UserControl and load it dynamically in codebehind when it's needed, then add it to your page. E.g, in code:
MyPopupControl popup = (MyPopupControl)Page.LoadControl("/path/to/usercontrol.ascx");
PopupPanel.Controls.Add(popup);
Where PopupPanel is an empty <asp:Panel>. Then, not even the markup will need to be loaded/processed except when its needed.
There is no reason that all the code you use to display and process this panel couldn't also be in the usercontrol, isolating it from the master page.
Can you build the panel dynamically, based on the cookie setting?
All the Google finds I ran into tell me how to use FindControl to access a control on the master from the content page itself.
However, what I'm trying to do is the opposite.
From the master page, I want to reference whichever child page is in the ContentPlaceHolder.
Why you ask.
I want the master page to know which tab should be active depending on the content Page currently in the placeholder.
This lets me avoid having each page to reference the master page and allow them to change the active tab; that should be the master page's job (if there's a way it can know whom it's enclosing).
Thanks. No rants please.
If you are looking to get the instance of the executing page class, you can retrieve it from the current HTTP context:
var page = HttpContext.Current.CurrentHandler as Page;
From there, you can navigate the page's control tree, call FindControl(), and so on. Be cautious about page lifecycle, though, as master page events tend to fire before their page event counterparts.
I have a Web Site project, and within it I have a user Web Control defined in an ascx file.
The control is added to the Site.Master, and it shows up correctly on the page and everything is fine.
I need to override some of the control's fields on one of the pages that derive from Site.Master.
// In OnLoad:
MyControlName control = (MyControlName) Page.Master.GetBaseMasterPage().FindControl("controlID"));
The issue is that MyControlName doesn't register as a valid Type on the child page. If I add a second instance of the control to the child page directly, the above works as needed, but if the control isn't placed directly on the page, and instead is only defined in the master page, the type is undefined. The control is not in a namespace, and is defined within the project, so I don't know why it is having such an issue location the appropriate type.
If I put a breakpoint in the OnLoad, the type listed for the control is ASP.my_control_name_ascx, but using that does not work either.
Why can't the child class reference the correct type? Can I fix this?
Thanks!
The control does not have global scope over the entire project. It will only be selectable as a type on pages where the control is registered. So you have to register the control on the child page:
<%# Register src="WebUserControl.ascx" tagname="WebUserControl" tagprefix="uc1" %>
You will need to add a register tag like above to the top of your child aspx page.
The other option is you could create an interface for the control which exposes the properties or methods you want to access, and put the interface in app_code or some other globally accessible place, then have the control implement the interface, and cast the control to the interface.
The following code works for me:
DropDownList ddlLanguage = (DropDownList)Page.Master.FindControl("ddlLanguage");
I take it GetBaseMasterPage() is your own method? What happens if you try:
MyControlName control = (MyControlName)Page.Master.FindControl("controlId");
?
Not a direct answer to your question, but you might find the #MasterType directive useful.
If you add a line like
<%# MasterType TypeName="ClientName.SiteName.MasterPages.SiteMaster" %>
to the top of your ASPX page, you should be able to refer to the master page in code without having to cast it. This might make it easier for the code to find your control, perhaps?
You could end up with a line like:
// In Page.OnLoad:
MyControlName control = Page.Master.MyControl;
and then expose a new property in your master page that wraps the FindControl call:
// In Site.master.cs
internal MyControlName MyControl
{
get { this.FindControl("controlID"); }
}
Hope this helps!
Is it possible to access an element on a Master page from the page loaded within the ContentPlaceHolder for the master?
I have a ListView that lists people's names in a navigation area on the Master page. I would like to update the ListView after a person has been added to the table that the ListView is data bound to. The ListView currently does not update it's values until the cache is reloaded. We have found that just re-running the ListView.DataBind() will update a listview's contents. We have not been able to run the ListView.DataBind() on a page that uses the Master page.
Below is a sample of what I wanted to do but a compiler error says
"PeopleListView does not exist in the current context"
GIS.master - Where ListView resides
...<asp:ListView ID="PeopleListView"...
GISInput_People.aspx - Uses GIS.master as it's master page
GISInput_People.aspx.cs
AddNewPerson()
{
// Add person to table
....
// Update Person List
PeopleListView.DataBind();
...
}
What would be the best way to resolve an issue like this in C# .Net?
I believe you could do this by using this.Master.FindControl or something similar, but you probably shouldn't - it requires the content page to know too much about the structure of the master page.
I would suggest another method, such as firing an event in the content area that the master could listen for and re-bind when fired.
Assuming the control is called "PeopleListView" on the master page
ListView peopleListView = (ListView)this.Master.FindControl("PeopleListView");
peopleListView.DataSource = [whatever];
peopleListView.DataBind();
But #palmsey is more correct, especially if your page could have the possibility of more than one master page. Decouple them and use an event.
Option 1 :you can create public property of your master page control
public TextBox PropMasterTextBox1
{
get { return txtMasterBox1; }
set { txtMasterBox1 = value; }
}
access it on content page like
Master.PropMasterTextBox1.Text="SomeString";
Option 2:
on Master page:
public string SetMasterTextBox1Text
{
get { return txtMasterBox1.Text; }
set { txtMasterBox1.Text = value; }
}
on Content Page:
Master.SetMasterTextBox1Text="someText";
option 3 :
you can create some public method that works for you
these approach is not so useful but it helps if you just want to use some limited and predefined control
One think to remember is the following ASP.NET directive.
<%# MasterType attribute="value" [attribute="value"...] %>
MSDN Reference
It will help you when referencing this.Master by creating a strongly typed reference to the master page. You can then reference your ListView without needing to CAST.
you can access with the code this.Master.FindControl(ControlID) which control you wish. It returns the reference of the control, so that the changes are effective. about firing an event could not be possible each situation.
Assuming your master page was named MyMaster:
(Master as MyMaster).PeopleListView.DataBind();
Edit: since PeopleListView will be declared protected by default, you will either need to change this to public, or create a public property wrapper so that you can access it from your page.