I am dealing with a master page split into various content placeholders as per usual. On a number of pages I use a multiview to show and hide the content based on different view modes (view / edit / add). This means one multiview per master page content placeholder...
The trouble comes when I need to switch view modes, eg from 'View' to 'Edit'. I need to change every multiview on the page to show the corresponding information. So say 4 different content placeholders exist, with 3 different view modes - thats 12 lines of quite tedious code.
I'm wondering if there is a way to sync or link all multiviews on a page, so that when one changes - they all change accordingly? Like through some sort of master multiview?
I've thought about using the View's Activate Event, but this would still mean doing a lot of wiring up to begin with, which is what I'm trying to avoid.
C#eers!
The best way to do this would be to have an event on the master page which the individual multiviews add an event handler to.
That should not need too much code, and you could avoid duplicating that code by creating a base class inheriting from MultiView for all your instances.
Another more automatic option (but not as performant as RobW's one), would be to recursively look on the page's controls for any multiview. Something like:
ApplyToControlsRecursive(Page, c =>
{
var multi = c as System.Web.UI.WebControls.MultiView;
if (multi != null)
multi.ActiveViewIndex = 1;
});
void ApplyToControlsRecursive(System.Web.UI.Control control, Action<System.Web.UI.Control> action)
{
action(control);
foreach (System.Web.UI.Control child in control.Controls)
{
ApplyToControlsRecursive(child, action);
}
}
Related
I received a new requirement today: For our product page, they want a completely different layout to be used based on the product type.
For example, say we sell buckets. Currently, all buckets use the exact same page layout. But now, they want wooden buckets to use the current layout, and plastic buckets to use a completely different layout. However, they want the URLs to stay the same (e.g., domain.com/bucket/1), so I can't just forward plastic buckets to a new page.
The current page structure is as follows:
CurrentMasterPage.master > CurrentProductPage.aspx > Several UserControls
The new layout requires new pages (i.e., none of the current ones are reused):
NewMasterPage.master > NewProductPage.aspx > Several UserControls
My first thought was to take all of the markup and code from CurrentProductPage.aspx and put it into a UserControl, then create a second UserControl for the new layout (NewProductPage.aspx), and have CurrentProductPage.aspx dynamically load the appropriate UserControl based on the product type, however, this doesn't work because the new layout requires a new MasterPage, and I can't reference a MasterPage from a UserControl.
Then, I thought about using URL Rewriting, but I don't think it's possible to have the same URL load two different pages.
Is there any way to accomplish this?
Why not use a 100% server side re-direct?
When you use response.Redirect("some different page"). Then the client side browser is sent a whole new copy of that page, and the URL will be updated.
However, the server side can write any page it wants to. The client side will not even know the server decided to dish out a different page for the given URL.
So, you could have a page with fake tabs as buttons. When the user hits a button, the browser round trip starts (for the given URL). But on server side, you can then dish out a different page for that URL.
So, in place of this classic "round trip", you can use:
Server.TransferRequest("MyotherWebPage")
So, for the given URL, before the current page (based on given URL) is sent down back to the browser, the above will simply pump out a different page. The current page will never make it back down to the browser.
In fact for a rich page with lots of buttons and features, you can change the page displayed. So in on-load - simply in place of a "response.Redirect", use a server.Transfer. The current page never makes it to the client - the one you dish out where. Because the client side has zero clue about what the web server decides to dish out - it will also have zero clue that a different page was send back to the client.
Try the above with a test page.
On page A, behind a standard button, jump to web page B
eg:
Response.Recdirect("MyPageB.aspx")
Note the URL change - classic round trip.
Now, do this with the button:
Server.Redirect("MyPageB.aspx")
In this case, no full round trip occurs. The server transfers directly to the new page and sends that out. (and note how your URL does NOT change).
You can change the Master Page on PreInit on the Page using a Master. This is possible because a Master is basically the same as a User Control and is loaded AFTER the page's code behind.
protected void Page_PreInit(object sender, EventArgs e)
{
if (NewProductPage)
{
MasterPageFile = "~/NewMasterPage.master";
}
}
I have two similar master pages, basically they are pretty extensive, but the difference relies in one using
common content
<form id="form1" runat="server" enctype="multipart/form-data">
common content
</form>
common content
and the other being
common content
<dn:Form id="form1" runat="server">
common content
</dn:Form>
common content
I was wondering how I could accomplish this, without having to create two master pages and just changing the form tags...
The way I currently though of doing this, is basically have one master page with the other content, a second one with the inner contents, and two others that just have the form tags and a placeholder inside them, and then dynamically choosing one master page over the other.
Is there a better way to do this or is this the correct way? thanks.
Update: I'm not sure my current idea is well expressed:
Base.master would have the outer contents, no inheritance.
Regular and Modified.master would have just the different form tags, both inherit from Base.Master
Shared.master would have the inner contents, inherit from Regular.Master and in case it requires the other form control, then it chooses the other master (which has the same ContentPlaceHolderID for FormContent), dynamically with something like this, maybe reading from web.config or the like
protected void Page_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "~/App_Shared/RegularWebForm.Master";
this.MasterPageFile = "~/App_Shared/UrlRewritableWebForm.Master";
}
The goal for this is being able to use the same Master page across three different applications for one same web domain.
The idea that my solution proposed would be that I have those four master page files in a given "App_Shared" folder, which is referenced via svn:externals from all the projects, so I don't have to repeat the code. The idea would be that I choose whether Shared.Master (which would be the functional base master page file for all three applications) uses the regular form or the user control in the current application, and that choice could be made by a setting in the web.config for the application.
In the master page code behind, you should be able to override OnInit (or OnLoad or in any number of other places) and determine when you need multipart encryption, and when you do, call:
Attributes.Add("enctype", "multipart/form-data");
Even better:
Expose a boolean property:
public bool EncodeMe {get;set;};
In each form that uses the master control set
Master.EncodeMe = true; // or false of course
then in the master page use the bool to determine whether or not to encode.
Is it possible to acces a control thats located in a content page (withing a content place holder, a multiview control to be more exactp) from the master page?
The situation is, i have a menu with buttons thats located in the master page.
Now in my content page i have 1 content place holder.
In which a multiview with several views is located.
If i press a button in the menu (MasterPage) then it should open the proper view (with its controls) displayed in the content place holder area.
I have set the ActieveViewIndex=0 but i am getting all sorts of wierd behavour.
I have to do something with the ActiveViewIndex++ somewhere but nothing seems to work.
edit::
string a = Request.Querystring["one"]
string b = Request.QueryString["two"]
if ( a == "addOne") // where addone is a redirection to the content page from the master page button
{
mvMultieView.SetActiveView(vView1);
}
else
if ( b == "addTwo")
{
mvMultieView.SetActiveView(vView2);
}
Any suggestions?
Kind Regards.
You can easily do that using find control
View myView = (View)this.Master.FindControl("PlaceHolderFullMain").FindControl("PlaceHolderMain").FindControl("Mymultiview")
The way my team and I accomplished this task (and I don't know that it's the best method, but it was effective) was to use query strings (as you had in your previous question it looks like). We established a standard QS variable called iView that would determine the name of the view in question (not necessarily the control name itself, but some keyword that the content control would respond to). Since all of our pages/controls have a page base class they inherit from, we put a method in the base class (in our case it was at the page level, but in yours a control level might work) that was responsible for getting the requested view. In the control we would have a mechanism (switch perhaps) that would set the activeView. In some cases we just used the actual ID of the control (since it was a mystery to be obfuscated) and avoided the switch altogether.
http://www.mydomain.com/mypage.com?iView=mySecondView
partial class MyControl : System.Web.UI.WebControl
{
// blah blah control stuff
public string getRequestedView()
{
return (Request.QueryString["iView"]) ? Request.QueryString["iView"] : String.Empty;
}
}
...
protected void Page_Load(object sender, EventArgs e)
{
View myView = myMultiView.FindControl(this.getRequestedView());
if(myView != null)
this.MyView.SetActiveView(myView);
}
have you done this change in the Master page or content page?
because i also got the same problem.
I have link buttons in my master page which i need to activate view controls in content page.
the content page is not the currently loaded page.
will this method help for my solution?
the problem i have is that i have multiple nested master pages:
level 1: global (header, footer, login, navigation, etc...)
level 2: specific (search pages, account pages, etc...)
level 3: the page itself
now, since only one form can have runat=server, i put the form at global page (so i can handle things like login, feedback, etc...).
now with this solution i'd have to also put the for example level 3 (see above) methods, such as search also on the level 1 master page, but this will lead to this page being heavy (for development) with code from all places, even those that are used on a single page only (change email form for example).
is there any way to delegate such methods from the onclick events (for example: ChangeEMail) from level 1 (global masterpage) to level 3 (the single page itself).
to be even more clear:
i want to NOT have to have the method ChangeEMail on the global master page code behind, but would like to 'MOVE' it somehow to the only page that will actually use it. the reason why it currently has to be on the global master is that global master has form runat=server and there can be only one of those per aspx page.
this way it will be easier (more logical) to structure the code.
thnx (hope i explained it correctly)
have searched but did not find any general info on handling this case, usualy the answer is: have all the methods on the master page, but i don't like it. so ANY way of moving it to the specific page would be awesome. thnx
edit also part of the same thing...
on the other hand - how to access the textbox1.text for example on the content page from master page? any best practice for this?
If you put the Search button and textbox on the .aspx itself (level 3) the event handler will also go in the page (or its codebehind). It doesn't matter that the form tag is on the global masterpage (level 1)
As for your second question: You can use
var tb = this.FindControl("textbox1") as TextBox;
I have an asp.net content page which is used inside of a master page (with header, menu and some links). I would like to reuse it in a different context without the master page (to not display the header and menu there), or with an empty master page if this is somehow possible. I don't want to violate DRY principle by taking the whole page and creating a standalone clone of it for obvious reasons. Is this somehow possible ?
Yes, you can set the master page dynamically in the content pages Page_PreInit method:
private void Page_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "MyMasterPage.master"
}
Set up some logic to dynamically choose which master page filename to pass in, and you are now sharing one content page with many master pages.
How about wrapping-up the shared content in a user control?
A user control is a kind of composite
control that works much like an
ASP.NET Web page—you can add existing
Web server controls and markup to a
user control, and define properties
and methods for the control. You can
then embed them in ASP.NET Web pages,
where they act as a unit.