Nested Master Pages and Inheritance - c#

I created a nested master page. The parent master page A inherits from System.Web.UI.MasterPage. The child master page B inherits from A.
I then created a web content page C which uses master page B, and inherits from System.Web.UI.Page.
From the web content page C I am able to access variables and methods from within both master pages. However the problem lies in accessing the parent master page variables and methods.
The problem is that a NullReferenceException is being raised. Variables and methods are not being initialised.
What is a possible solution?
public partial class ParentMasterPage : System.Web.UI.MasterPage
{
internal Button btn_Parent
{
get { return btn; }
}
}
public partial class ChildMasterPage : ParentMasterPage
{
internal Button btn_Child
{
get { return btn; }
}
}
public partial class WebContentPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
Button tempA = Master.btn_Child; //WORKS
Button tempB = Master.btn_Parent; //NULL REFERENCE EXCEPTION
}
}

A nested master page does not inherit it's parent master page's type. Instead it composes itself such that the NestedMasterType.Master property is an instance of the parent master page. The NestedMasterType type still inherits from System.Web.UI.MasterPage.
So this is right:
public partial class ChildMasterPage : System.Web.UI.MasterPage
This is wrong:
public partial class ChildMasterPage : ParentMasterPage
You would then access the (parent) Master of the (child) Master of a Page (that uses the child master) like this:
Button tempA = ((ChildMasterPage)this.Master).btn_Child;
Button tempB = ((ParentMasterPage)this.Master.Master).btn_Parent;
Note: This answer assumes that you mean that ChildMasterPage is a nested master page, that uses a Master directive similar to the below:
<%# Master MasterPageFile="~/ParentMasterPage.Master" Inherits="ChildMasterPage"...

A Page only has a reference to it's immediate master and it's variables, you would have to traverse up the object graph to the main master page i.e.
var parentMaster = (ParentMasterPage)Page.Master.Master;
parentMaster.SomeProperty = ...;
Alternatively, you could bridge the gap between the 2 by implementing the same property in your ChildMasterPage i.e.
internal Button btn_Parent
{
get { return ((ParentMasterPage)Master).btn_Parent; }
}
This would mean the code you currently have would work, however, it sort of defeats the purpose of having a main master page.

Related

Cast Page for accessing textbox/object of other page

Previously, I had only one xaml-file, which was the only Windows, namely the mainWindow.
To access any button / textbox / object from another class (explicetly a non-static class) I can just cast the Window like this
mainWindow mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is mainWindow) as mainWindow;
Now my question is, how does this work for several pages, since now I have a Frame, where I load several pages to.
Actually it does NOT work like this:
myPage page = Application.Current.Windows.Cast<Page>().FirstOrDefault(p => p is myPage) as myPage;
There is a runtime-error, which says:
System.InvalidCastException: Object of type "namespace.mainWindows" cannot be converted to object of type "System.Windows.Controls.Page"
make MainWindow return a Page, which is displayed:
public class mainWindow
{
public Page GetCurrentPage()
{
// return known Page;
};
}
and then:
mainWindow mainWin = Application.Current.Windows.OfType<mainWindow>().FirstOrDefault();
Page p = mainWin?.GetCurrentPage();
This one worked out for me:
MainWindow
namespace myName
{
public partial class main : Window
{
public main()
{
// ...
}
}
}
Textbox and Frame, where the page is load into, in the xaml-file of the mainWindow
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_main" Text="testString main" x:FieldModifier="public"/>
<Frame x:Name="myFrame" x:FieldModifier="public"/>
Page
namespace myName
{
public partial class myPage : Page
{
public myPage()
{
// ...
}
}
}
Textbox in the xaml-file of the Page
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_page" Text="testString page" x:FieldModifier="public"/>
After that, one is able to access the two textboxes (one directly in the window, one in a page of the window) in any other class via the following commands:
// get instance of the main-Window
main mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is main) as main;
// Access objects of the main-Window
Console.WriteLine(mainWin.textbox_main.Text);
// get instance of the current page of the certain frame
myPage page = (myPage)Application.Current.Windows.OfType<main>().FirstOrDefault().myFrame.Content;
// Access objects of the page
Console.WriteLine(page.textbox_page.Text);

How to access Child Context in UWP Frame?

Can you tell me How to access Child Context in UWP Frame??
(I'm using Frame Control. (MyFrame is Frame Control)
public sealed partial class MyPage: Page
{
public MyPage()
{
this.InitializeComponent();
MyFrame.Navigate(typeof(Pages.ChildPage));
}
}
so, how to access the context of 'Pages.ChildPage'??
for example,
Pages.ChildPage.iTestVariable = 1;
Pages.ChildPage.doTestFunction();
You can access the child page after navigation like this:
var childPage = MyFrame.Content as Pages.ChildPage;
if ( childPage != null )
{
childPage.doTestFunction();
}
Of course, it is necessary to keep in mind that you can access only public methods and properties from outside the class itself.

MasterPage Access Controls

I have 2 master page in my web site.
MainMaster
SubMaster (Master Page:MainMaster)
Page (Master Page:SubMaster)
I have hidden fields on SubMasterPage. And i'm proccessing datas and setting hidden field value on SubMasterPage Init event. I want to get hiddenfield's value from Page.aspx
I'm trying this on Page.aspx, getting "Object reference not set to an instance of an object." error
((HiddenField)this.Master.FindControl("hiddenId")).Value
But when i have 1 master page this code works normally.
Have i a solution in this problem? Or should i try transfer datas via session/querystring e.t.c.?
You could add a property to your sub master page to return the value, and use this in the child page.
eg.
Sub Master Page
public string HiddenValue
{
get
{
//return the value of your hidden field
return HiddenID.Value;
}
}
Child page:
//Method to get the hidden value from the master page, if the master page is a sub master page
private string GetHiddenValue()
{
if (this.Master is SubMasterPage)
{
string value = (this.Master as SubMasterPage).HiddenValue;
return value;
}
else
{
return string.Empty;
}
}
if you want to go one step further you could add an extension method to the MasterPage class to call it easily from any page.
eg:
public static class MasterPageExtensions
{
public static string GetHiddenFieldValue(this MasterPage master)
{
if (master is SubMasterPage)
return (master as SubMasterPage).HiddenFieldValue;
else
return string.Empty;
}
}
public class SubMasterPage : MasterPage
{
private HiddenField _hiddenField;
public string HiddenFieldValue
{
get
{
return _hiddenField.Value;
}
}
}
public class ChildPage : Page
{
void TestMethod()
{
string hiddenValue = this.Master.GetHiddenFieldValue();
}
}
this is particularly useful when for example you have a single modal popup message box on the master page, and you want to show it from any child page.

MasterPage objects returning as null

I've got an ASP.net application that is used to display information queried from our ERP system onto various web pages. The main object is called an EpicorUser, and it basically encapsulates all current information about an employee.
This object is used to fill in a bunch of various fields on the master page such as Full Name, current activity, clock in/out times, etc.
I am trying to pass this object from the MasterPage into the content pages to avoid needlessly querying the WebService that serves this information. The problem is, when I access the object from a ContentPage, it is always null. I know it has been populated because my MasterPage content is all filled in correctly.
I am trying to access the MasterPage 'CurrentUser' object from my ContentPage like this:
**MasterPage Codebehind:**
public EpicorUser CurrentUser; //This object is populated once user has authenticated
///This is in my ContentPage ASPX file so I can reference the MasterPage from codebehind
<%# MasterType VirtualPath="~/Pages/MasterPage/ShopConnect.Master" %>
**ContentPage CodeBehind:**
string FullName = Master.CurrentUser.UserFileData.FullName; //CurrentUser is null(but it shouldn't be)
Strange thing is, I had another content page where this system worked fine. It has also stopped working, and I don't think I have changed anything on the masterpage that could cause this. I had set the CurrentUser as a public property so I could access
I went as far a creating a method to re-populate the object from the master page, and calling it from the code-behind on the contentpage:
**ContentPage code-behind:**
EpicorUser CurrentUser = Master.GetCurrentUserObject();
**MasterPage Method being invoked:**
public EpicorUser GetCurrentUserObject()
{
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "OFFICE"))
{
UserPrincipal principal = UserPrincipal.FindByIdentity(context, HttpContext.Current.User.Identity.Name);
EpicorUser CurrentEmployee = RetrieveUserInfoByWindowsID(principal.SamAccountName);
return CurrentUser; //Object is NOT null before the return
}
}
**ContentPage code-behind return:**
EpicorUser CurrentUser = Master.GetCurrentUserObject(); //But object is now null once we return
Stepping through the code shows me that the CurrentUser object is populated correctly in the MasterPage code behind, but once it is returned to the ContentPage code behind, it is now null!
Anyone know where the disconnect is?
Content Page is loaded first and then Master page will be loaded. So, your property could be blank when it is accessed in the content page. You can try creating a public method(to return UserObject) on the master page and then call the method from content page.
Another option is
creating a base page class(inherit all content pages) and create a property to return the user object. So, all pages can access the value
EDIT:
public class BasePageClass : System.Web.UI.Page
{
public List<string> LookupValues
{
get
{
if (ViewState["LookupValues"] == null)
{
/*
* create default instance here or retrieve values from Database for one time purpose
*/
ViewState["LookupValues"] = new List<string>();
}
return ViewState["LookupValues"] as List<string>;
}
}
}
public partial class WebForm6 : BasePageClass
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void MyButton_Click(object sender, EventArgs e)
{
//access lookup properties
List<string> myValues = LookupValues;
}
}

Accessing different Masterpages from Base Class

I have an application that uses 2 master pages. One for main pages and one for Popup pages. These both inherit from Masterpages
public partial class MainMasterPage : System.Web.UI.MasterPage
{
UserBO objUser = null;
public UserBO GetCurrentUser()
{
UserBO userBO = new UserBO();
.....
.....
return userBO;
}
}
public partial class PopupMasterPage : System.Web.UI.MasterPage
{
UserBO objUser = null;
public UserBO GetCurrentUser()
{
UserBO userBO = new UserBO();
.....
.....
return userBO;
}
}
So far so good. So my content pages all Inherit from a base class. The base class has a method that
calls the GetCurrentUser from the Base class.
public class BasePage : Page
{
//.....
protected UserBO GetCurrentUserFromMasterPage()
{
this.Master
Elsa.MasterPages.MainMasterPage master = (Elsa.MasterPages.MainMasterPage )this.Master;
return master.GetCurrentUser();
}
}
So here you can see that the base page casts the MasterPage and then calls GetCurrentUser.
Just for background... The masterpages get current user logged into the system and then draws itself using the info. If the user is in the session it gets it otherwise it loads from the database. I dont want the content pages to do the same so I wanted the base page to always get the current user for the content page from the master.
However my problem is, that because there is 2 master pages and all web pages are derived from Base
page.. I need to be able to cast to the correct master.
public partial class MyMainPage : Elsa.Pages.BasePage
{
private long _userId = -1;
public partial class MyPopupPage : Elsa.Pages.BasePage
{
private long _userId = -1;
If I put in the MasterType directive I can call the method in the content page for the correct Master.
But I dont want to call it from the content as its common method so I need it in the base.
So does anyone know how to handle this. I was thinking on deriving the BasePage again for a PopupBasePage and over writing the GetCurrentUserFromMasterPage() to cast to the popup master.
Or do I pass something into the BasePage constructor to tell it what to cast to.
I want to keep the impact to all my web pages to a minium as I have a lot of web pages.
Thanks M
You can insert an extra MasterPage as the base class for your 2 current ones:
public partial class SiteMasterPage : System.Web.UI.MasterPage
{
....
// GetCurrentUser
}
public partial class MainMasterPage : SiteMasterPage
{
....
}
public partial class PopupMasterPage : SiteMasterPage
{
}
This will allow you to implement other common features and markup (include of CSS files) in one place as well.
Does it make sense for you
using Reflection:
Master.GetType().GetMethod("GetCurrentUser").Invoke();
Do this :-
public class MasterPageBase : MasterPage
{
public PageBase PageBase { get { return (PageBase)this.Page; } }
}
public class PageBase : Page
{
// Do your Extensions Here..
}
All Pages there after Inherit from PageBase.

Categories

Resources