Dynamically choose a theme - c#

NET, I recently buy a book to start by myself and try to follow the exercises.
I was aware that you can apply a theme in the tag of a web config file by just adding "theme" property, however the following exercise was to choose a theme from a dropdownlist which I couldn't understand very well and is simply not working for me.
Here is the master page cs code (Book's code)
namespace WebApplication7
{
public partial class SiteMaster : MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string selectedTheme = Page.Theme;
HttpCookie preferredTheme = Request.Cookies.Get("PreferredTheme");
if (preferredTheme != null)
{
selectedTheme = preferredTheme.Value;
}
if (!string.IsNullOrEmpty(selectedTheme))
{
ListItem item = ThemeList.Items.FindByValue(selectedTheme);
if (item != null)
{
item.Selected = true;
}
}
}
}
protected void Theme_SelectedIndexChanged(object sender, EventArgs e)
{
HttpCookie preferredTheme = new HttpCookie("PreferredTheme");
preferredTheme.Expires = DateTime.Now.AddMonths(3);
preferredTheme.Value = ThemeList.SelectedValue;
Response.Cookies.Add(preferredTheme);
Response.Redirect(Request.Url.ToString());
}
}
}
Here is the dropdownlist
<asp:DropDownList ID="ThemeList" runat="server" OnSelectedIndexChanged="Theme_SelectedIndexChanged" AutoPostBack="True">
<asp:ListItem Value="monochrome" >Monochrome</asp:ListItem>
<asp:ListItem Value="colors">Colors</asp:ListItem>
</asp:DropDownList>
This is an example of the book "Beginning ASP.NET 4.5.1: in C# and VB"
The book doesn't mention any missing step and to be honest I don't understand how the drop down list "indexchanged" is linked to the themes I created in the App_Themes folder. I am just assuming this is related to "Page.Theme".
Thanks in advance.

The book includes this code:
to set the theme.
I suspect you should read the entire chapter, you need to do all of it to make it work. You can also read the entire source code (to compare with yours).

Yes I had to create a new Asp.net folder, then App_Code folder, create a BasePage.cs folder, right click and set that file to compile, Copy and Paste the code missing in BasePage.cs.
After apply all the inheritance from Page to BasePage in all my aspx pages and done.
Thank you for your answer.

Related

WebForms model binding insert stopped working

I am using webforms model binding on EF6 code first project. I have a page that was working perfectly. It stopped working with no apparent reason. The insert method is not called anymore. I have another insert page and it works perfectly still. Anyone know of anything that would cause this?
Here is some of the markup that it is using.
<asp:FormView runat="server" ID="fvTour"
ItemType="CommonInterface.Tour" DefaultMode="Insert"
InsertItemPosition="FirstItem" InsertMethod="InsertItem"
OnItemCommand="ItemCommand" RenderOuterTable="false">
Code behind
public void InsertItem()
{
using (_db)
{
FileUpload picUpload = (FileUpload)fvTour.FindControl("fuploadTour");
if (picUpload == null || !picUpload.HasFile) return;
var item = new CommonInterface.Tour();
item.MemberID = (int)Session["MemberID"];
item.FID = LoginBLL.GetFID(item.MemberID);
item.TourSubmitDate = DateTime.Now;
item.PID = null;
item.TourState = ((DropDownList)fvTour.FindControl("ddlState")).SelectedItem.Text;
item.TourCounty = ((DropDownList)fvTour.FindControl("ddlCounties")).SelectedItem.Text;
item.TourLayout = ((DropDownList)fvTour.FindControl("ddlLayout")).SelectedItem.Text;
item.TourType = ((DropDownList)fvTour.FindControl("ddlType")).SelectedItem.Text;
TryUpdateModel(item);
if (ModelState.IsValid)
{
// Save changes
_db.Tours.Add(item);
_db.SaveChanges();
Response.Redirect("Default");
}
}
}
Edit 2:
Try to use OnItemCommand and see if that works. Set OnItemCommand="ItemCommand" back to your markup and try the following on code behind:
public void ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName == "Insert")
{
InsertItem();
}
}
Make sure that the button you press has a CommandName="Insert" attribute set.
You should be able to set a breakpoint on this method at least. Then you can see if the button fires an event at all.

masterpage initializeculture no suitable method found to override error?

I'm trying to develop a MultiLanguage web site using ASP.NET with C#
My problem is: I want to make my MasterPage support switching among languages, but when i put the "InitializeCulture()" inside the masterpage.cs, I got this error.
this is my code:
public partial class BasicMasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
if (e.Day.IsToday)
{
e.Cell.Style.Add("background-color", "#3556bf");
e.Cell.Style.Add("font-weight", "bold");
}
}
Dictionary<string, System.Globalization.Calendar> Calendars =
new Dictionary<string, System.Globalization.Calendar>()
{
{"GregorianCalendar", new GregorianCalendar()},
{"HebrewCalendar", new HebrewCalendar()},
{"HijriCalendar", new HijriCalendar()},
{"JapaneseCalendar", new JapaneseCalendar()},
{"JulianCalendar", new JulianCalendar()},
{"KoreanCalendar", new KoreanCalendar()},
{"TaiwanCalendar", new TaiwanCalendar()},
{"ThaiBuddhistCalendar", new ThaiBuddhistCalendar ()}
};
protected override void InitializeCulture()
{
if (Request.Form["LocaleChoice"] != null)
{
string selected = Request.Form["LocaleChoice"];
string[] calendarSetting = selected.Split('|');
string selectedLanguage = calendarSetting[0];
CultureInfo culture = CultureInfo.CreateSpecificCulture(selectedLanguage);
if (calendarSetting.Length > 1)
{
string selectedCalendar = calendarSetting[1];
var cal = culture.Calendar;
if (Calendars.TryGetValue(selectedCalendar, out cal))
culture.DateTimeFormat.Calendar = cal;
}
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
base.InitializeCulture();
}
}
How can I create a Base class?
The method InitializeCulture() exists only on the Page class, not the MasterPage class, and that's why you get that error.
To fix this, you could create a BasePage that all your specific pages inherit:
Create a new Class (not Webform), call it BasePage, or whatever you want.
Make it inherit System.Web.UI.Page.
Make all your other pages inherit the BasePage.
Here's an example:
public class BasePage : System.Web.UI.Page
{
protected override void InitializeCulture()
{
//Do the logic you want for all pages that inherit the BasePage.
}
}
And the specific pages should look something like this:
public partial class _Default : BasePage //Instead of it System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Your logic.
}
//Your logic.
}
There is an alternate solution that DOES NOT require you to create a BasePage.
The problem with 'Culture' is that it gets set very very early on the page life cycle, so the Page.InitializeCulture event is one of the early events on the page (if not the only one) where we can hook up to change the Thread.CurrentThread.CurrentUICulture. But what if we do that even earlier, as soon as the Request begins on the server.
I do that on the Application_BeginRequest event on the Global.asax file which is called on every request.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpCookie cookie = Request.Cookies["langCookie"];
if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value);
}
}
There I check for the existence of a cookie that holds the culture I want to use. If there's no cookie, then the default culture will be used.
To change the language on my application I just need a control that changes the cookie value client-side and then do a simple postback to the server. It doesn't matter if such control is on the Content Page or in the Master Page, it doesn't even need any code on the server-side, because all the processing is done on the method above, and the cookie gets set on the client-side even before the page is posted.
I've used a simple LinkButton (which is styled as a Mexican Flag), but you can use any other control that do a postback when clicked/changed.
<asp:LinkButton ID="btnSpanish" runat="server" OnClientClick="SetLanguageCookie('es')" CausesValidation="false" CssClass="mxFlag" />
Right before this button posts back to the server, it runs the client-side click event which updates the cookie value I want to set, and voila!
I have the javascript code that sets the cookie at the Master Page head section:
function SetLanguageCookie(selectedLanguage) {
var expDate = new Date();
expDate.setDate(expDate.getDate() + 20); // Expiration 20 days from today
document.cookie = "langCookie=" + selectedLanguage + "; expires=" + expDate.toUTCString() + "; path=/";
};
That's it!! The Thread.CurrentThread.CurrentUICulture gets changed and no BasePage class is needed nor overriding the Page.InitializeCulture method. There's even the side effect that the language selected is remembered on following visits since it's stored on a cookie.
If you want to use a DropDownList instead of a LinkButton, just make sure to set the AutoPostBack="true" and, since there is no OnClientChanged property for the DropDownList, you must hardcode the onchange attribute on the DropDownList and pass the selected value to the same javascript function.
<asp:DropDownList ID="ddlLanguage" runat="server" AutoPostBack="true" onchange="SetLanguageCookie(this.options[this.selectedIndex].value)">
<asp:ListItem Text="English" Value="en" />
<asp:ListItem Text="Español" Value="es" />
<asp:ListItem Text="Français" Value="fr" />
</asp:DropDownList>
The onchange attribute is not part of the DropDownList properties, however, since the DropDownList is an analog control of the <select> control, the attribute is just placed 'as is' when the rendering happens, and it's rendered before the postback mechanism code. Here's the HTML rendered by the DropDownList above:
<select name="ctl00$cph1$ddlLanguage" onchange="SetLanguageCookie(this.options[this.selectedIndex].value);setTimeout('__doPostBack(\'ctl00$cph1$ddlLanguage\',\'\')', 0)" id="cph1_ddlLanguage">
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
Hope someone finds this approach as useful as I do. :)

How to remove the error like "Expected ;" in Tridion popup page?

I am customizing the ribbon toolbar and adding a button to it. Whenever I click on that button, it will open a aspx page allows authors to select some data, which gets appended to the existing RTF field content.
But when popup is opened it is having the below error in the browser (Internet Explorer).
I am inheriting Tridion page in the code behind file. When I try to use Response.Write() functions it is giving error like "Expected ;". Please tell me the reason why it is giving the error like that? Early responce is appreciated. Thanks in advance.
PFB the related code:
Aspx page code behind file contents:
namespace ButtonReference.Popups
{
[ControlResourcesDependency(new Type[] { typeof(Popup), typeof(Tridion.Web.UI.Controls.Button), typeof(Stack), typeof(Dropdown), typeof(List) })]
[ControlResources("RTFExtensions.ButtonReferenece")]
public partial class PopupReference : TridionPage
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
TridionManager tm = new TridionManager();
tm.Editor = "PowerTools";
System.Web.UI.HtmlControls.HtmlGenericControl dep = new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep.InnerText = "Tridion.Web.UI.Editors.CME";
tm.dependencies.Add(dep);
System.Web.UI.HtmlControls.HtmlGenericControl dep2 = new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep2.InnerText = "Tridion.Web.UI.Editors.CME.commands";
tm.dependencies.Add(dep2);
//Add them to the Head section
this.Header.Controls.Add(tm); //At(0, tm);
}
protected void Page_Load(object sender, EventArgs e)
{
mySession = new Tridion.ContentManager.Session(#"");
if (!Page.IsPostBack)
{
try
{
if (true)
{}
else
{
//Response.Write("Invalid schema chosen");
return;
}
}
}
}
}
Small remark: since your page will be used as a simple popup, you don't need to load Domain Model related JavaScript stuff. Not loading it will reduce the load time for your page. To do that you need to set IsStandAloneView Tridion Manager property to false:
tm.IsStandAloneView = false;

Dynamically change MasterPage and ContentPlaceHolderID of asp content tag?

I have a page which initially inherited from MastePage.master . And I want to use the same page but with different masterpage(MasterPage2.master) at some other place in my project. For that I am using the following code.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
Content con = new Content();
con = (Content)this.FindControl("Content1");
this.Content1.ContentPlaceHolderID = "ContentPlaceHolder2";
}
}
I am also trying to set the asp content tag's ContentPlaceHolderID to ContentPlaceHolder2 which is from MasterPage2.master. Initially it was ContentPlaceHolder1.
But I am getting null value at con = (Content)this.FindControl("Content1");
Thanks
Page internally stores in private '_contentTemplateCollection' hashtable. it uses ContentPlaceHolderID property as key and stores special class (that will be used to build/initialize Content tag) as a value
- so to change ContentPlaceHolderID value (defined within markup) you need to modify this hashtable, remove old entry linked with old Id and add other entry with new Id
- you need to change ContentPlaceHolderId before creating master page otherwise an exception will be thrown in runtime
- best place to change Ids is Page 'preinit' event and if it is better to change Ids before change master page (if you will change master page at runtime)
To change ContentPlaceHolderID of Content tag, you can use following function in Page PreInit event
public static void AssignContentToNewPlaceHoldersWithinPage(Page pPage, string pOldId, string pNewId)
{
if (pPage == null || string.IsNullOrEmpty(pOldId) || string.IsNullOrEmpty(pNewId))
{
return;
}
// Try to get a reference to private hashtable using fasterflect free reflection library in codeplex (http://fasterflect.codeplex.com/)
// you can replace following line with standard reflection APIs
var lTmpObj = pPage.TryGetFieldValue("_contentTemplateCollection");
if (lTmpObj != null && lTmpObj is Hashtable)
{
var _contentTemplateCollection = lTmpObj as Hashtable;
if (_contentTemplateCollection.ContainsKey(pOldId) && !_contentTemplateCollection.ContainsKey(pNewId))
{
var lTemplate = _contentTemplateCollection[pOldId];
_contentTemplateCollection.Add(pNewId, lTemplate);
_contentTemplateCollection.Remove(pOldId);
}
}
}
function parameter are
pPage is reference to page instance contains content tag
pOldId is ContentPlaceHolderId property value in markup - the Id you want to change
pNewId is the new Id you want to use
I hope that my answer will be useful and I am sorry if my English language is not good
You can dynamically change the Master Page at runtime, but you need to use the same ContentPlaceHolder IDs. That way, your pages will work with either Master Page without adding extra code to change the IDs at runtime.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
}
}
You can even test that your page will work with either Master Page in the Visual Studio design/markup view by changing the MasterPageFile in the <% Page %> directive in the .aspx markup.
The Master Page can be changed by overriding OnPreInit.
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = "~/MasterPages/MyOther.Master";
}
But for the ContentPlaceHolders I would suggest to create new ContentPlaceHolders with the same name in both of your MasterPages.

How to select current menu in master pages?

In my web app (asp.net C#) I have menus as "All", "Education", "Fun", "Comedy". I want when I select All then it should be displayed as current menu, for which I have a CSS class current.
In case of WebUserControls I can do it easily by passing parameter of current page to select as below:
mywebpage.aspx
<uc:header ID="header1" runat="server" selectedMenu="comedy" />
header.ascx (code (c#))
public string selectedMenu
{
get { return strSelected; }
set { strSelected = value; }
}
header.ascx (html)
<ul>
<li><a href="/all/" title="All Videos" <%if (strSelected == "all"){%>class="current"<%} %>><span>All</span></a></li>
<li><a href="/fun/" title="Fun Videos" <%if (strSelected == "fun"){%>class="current"<%} %>><span>Fun</span></a></li>
<li><a href="/comedy/" title="Comedy Videos" <%if (strSelected == "comedy"){%>class="current"<%} %>><span>Comedy</span></a></li>
</ul>
When I'll pass comedy from my webpage to usercontrol then it will select comedy menu. I want to implement the same kind of functionality in case of master pages, could anyone tell me how to achieve this type of facility for master pages.
One way what I feel is to pass a query string parameter http://example.com/all/?select=all, I'll check on master page_load function if select parameter is "all" or fun or comedy then select corresponding menu. But this is not good, because I don't want to add an extra query string parameter to my URLs.
Please tell me how to solve this issue.
Thanks
You can access master page properties from your content page after casting the master to the correct type:
public class MyMasterPage : MasterPage
{
public string MyMenuProperty { get; set; }
protected void Page_PreRender(object sender, EventArgs e)
{
if (MyMenuProperty == "comedy")
{
/* do your menu stuff */
}
}
}
public class MyContentPage : Page
{
protected void Page_Load(object sender, EventArgs e)
{
var myMaster = Page.Master as MyMasterPage;
if (myMaster != null)
{
myMaster.MyMenuProperty = "comedy";
}
}
One way i have done simular in the past is add this to the page derivatives of any content pages:
<%# MasterType VirtualPath="~/YourMaster.master" %>
Then in the master i exposed this:
private PageTypes currentPageType;
public PageTypes CurrentPageType
{
get { return currentPageType; }
set { currentPageType = value; }
}
On this job this was used so the master knew what type of page it was on and therefore changed a few things, colours, controls etc. So from a contents pageload i did
Master.CurrentPageType = PageTypes.System;
One thing to note however, VS tends to moan about the MasterType derivative until you do a rebuild all.
I'm thinking that maybe a completely different approach might be easier to implement and maintain.
How about you just parse the URL in your header.ascx?
For example:
<li><a href="/all/" title="All Videos" runat="server" class='<%= Request.Url.ToString().Contains("/all/") ? "current" : "" %>' ><span>All</span></a></li>
That way, you won't have to worry about setting properties, accessing/casting master pages etc...
Hai prashant,
I had the same issue a month back and i posted in stack overflow check this one it may help you Find a UnorderedList <UL> control inside a master page from a content page in asp.net

Categories

Resources