Access Master Page class in C# .Net 3.5 - c#

So... I'm having to get someone's old (2010) .Net 3.5 C# code working... and of course the dev didn't have the project files anymore just the source...
Long story is code is trying to access a property of the master page class and this looks like it should be working according to everything I can find but it's not.
Example of the MasterPage code behind:
public partial class myMasterPage : System.Web.UI.MasterPage
{
private string pageName = "";
public string PageName
{
get { return PageName; }
set { pageName = value; }
}
private int pageID;
public int PageID
{
get { return pageID; }
set { pageID = value; }
}
}
One of the pages code:
<%# Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="Help" Codebehind="Help.aspx.cs" %>
<%# MasterType TypeName="ISLMasterPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
And finally the code behind for that page:
public partial class Help : BasePage
{
protected void Page_PreInit(object sender, EventArgs e)
{
base.PageID = 1;
Master.PageID = 1;
}
}
I've tried changing the MasterType to virtual path... nothing... error I'm getting is:
E'System.Web.UI.MasterPage' does not contain a definition for 'PageID' and no extension method 'PageID' accepting a first argument of type 'System.Web.UI.MasterPage' could be found (are you missing a using directive or an assembly reference?)
So to me it's obvious that it's not picking up the fact that we want the code behind.
I'm guessing this is something obvious but I've never organized my code in such a way.

Your code doesn't know that your master page is a "myMasterPage"
protected void Page_PreInit(object sender, EventArgs e)
{
base.PageID = 1;
(Master as myMasterPage).PageID = 1;
}

It seems your code has inherited a BasePage
public partial class Help : BasePage
It overrides the normal System.Web.UI.Page and enables easy access to properties on every page where BasePage is used.
In the BasePage class there could be something like this:
public class BasePage : System.Web.UI.Page
{
public Site master;
public BasePage()
{
this.Load += new EventHandler(this.Page_Load);
}
protected void Page_Load(object sender, EventArgs e)
{
master = ((Site)(Page.Master));
}
}
In this example the Master Page is always accessible with master on the pages that inherit BasePage

Related

Compilation error when dynamically setting property of user control inside repeater

In a C# Webforms website (not web application), I have the following set up:
A page, which includes Step.ascx which includes an asp:Repeater.
The repeater in Step.ascx displays all sections (Section.ascx) within this step.
SectionInfoProvider.GetSections(1).ToList() returns a list of SectionInfo, which is a class several properties including DisplayName as string.
I'm getting a compilation error (The type or namespace name could not be found) when trying to dynamically set the SectionInfo property of the Section user control into the repeater in Step.ascx.cs. I've tried using the partial class name of the user control, and UserControl, but neither work.
I'm also trying to create a collection of SectionControls because I want to use that for something else on the page too.
What am I doing wrong here?
Step.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="~/Step.ascx.cs" Inherits="Custom_Step" %>
<%# Register TagPrefix="uc" TagName="Section" Src="~/Section.ascx" %>
<asp:Repeater runat="server" ID="rptSections" OnItemDataBound="rptSections_OnItemDataBound" EnableViewState="True">
<ItemTemplate>
<uc:Section runat="server" ID="Section" EnableViewState="True"/>
</ItemTemplate>
</asp:Repeater>
Step.ascx.cs
public partial class Custom_Step : System.Web.UI.UserControl
{
public IEnumerable<SectionInfo> Sections { get; set; }
private IEnumerable<???> SectionControls { get; set; } <-- What should ??? be?
protected override void OnLoad(EventArgs e)
{
Sections = SectionInfoProvider.GetSections(1).ToList();
rptSections.DataSource = Sections;
rptSections.DataBind();
}
protected void rptSections_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
var info = (SectionInfo)e.Item.DataItem;
var ctrl = (???)e.Item.FindControl("Section"); <-- What should ??? be?
ctrl.SectionInfo = info;
if (SectionControls == null) SectionControls = new List<???>(); <-- What should ??? be?
((List<???>)SectionControls).Add(ctrl); <-- What should ??? be?
}
}
Section.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="~/Section.ascx.cs" Inherits="Custom_Section " %>
<h3><asp:Literal runat="server" ID="litSectionHeading" /></h3>
Section.ascx.cs:
public partial class Custom_Section : System.Web.UI.UserControl
{
public SectionInfo SectionInfo { get; set; }
protected override void OnLoad(EventArgs e)
{
litSectionHeading.Text = SectionInfo.DisplayName;
}
}
I think you just need a typecast and an if.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {`
...
var ctrl = e.Item.FindControl<Custom_Section>("Section");`
or
var ctrl = (Section)e.Item.FindControl("Section");
...
}
Is that something you already tried?
Creating the dynamic controls can be done but that's a separate question.

Splitting up WebMethods into multiple files

I previously had a single .aspx.cs file that contained numerous WebMethods. It looked something like this:
// webmethods.aspx.cs
public partial class Default : System.Web.UI.Page {
[System.Web.Services.WebMethod]
public static string Method1() {
}
[System.Web.Services.WebMethod]
public static string Method2() {
}
[System.Web.Services.WebMethod]
public static string Method3() {
}
}
And the corresponding .aspx file, that looked something like this:
<%# Page Language="C#" MasterPageFile="Navigation.master" AutoEventWireup="true" CodeFile="webmethods.aspx.cs" Inherits="Default" Debug="true" %>
I was able to then call my WebMethods successfully using AJAX.
But the webmethods.aspx.cs file was getting very large, and I wanted to split the WebMethods up into different files. So I did that like this:
webmethods.aspx.cs:
// first file
namespace Foo {
public partial class Default : System.Web.UI.Page {
[System.Web.Services.WebMethod]
public static string Method1() {
}
}
webmethods2.aspx.cs:
// second file
namespace Foo {
public partial class Default : System.Web.UI.Page {
[System.Web.Services.WebMethod]
public static string Method2() {
}
}
webmethods3.aspx:
// third file
namespace Foo {
public partial class Default : System.Web.UI.Page {
[System.Web.Services.WebMethod]
public static string Method3() {
}
}
And changed the page directive to Inherits="Foo.Default".
But now, every time I try to access any of the WebMethods in the other files via AJAX, I get an Unknown WebMethod error. The AJAX request is still being sent to the webmethods.aspx.cs file.
Can someone help guide me as to what I did wrong?
WebForm compilation model allows single CodeBehind file for a partial class which compiles into a single .dll. All files in App_code folder also compile in a single file before compilation of .aspx and .aspx.cs. So workaround may look like this.
//Default.aspx
<!DOCTYPE html>
<%# Page Language="C#" AutoEventWireup="true" Inherits="SomeApp.MyPage" %>
<%-- No CodeBehind. inherits external class--%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="lblTest"></asp:Label><br />
<asp:Button runat="server" ID="btnTest" Text="click me" OnClick="btnTest_Click" />
</div>
</form>
</body>
</html>
//App_Code\MyPage.cs
namespace SomeApp
{
public partial class MyPage : System.Web.UI.Page
{
//You need to declare all page controls referred by code here
public System.Web.UI.WebControls.Label lblTest { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
lblTest.Text = "hello world from app_code";
}
}
}
}
//App_code\AnotherFile.cs
namespace SomeApp
{
public partial class MyPage : System.Web.UI.Page
{
protected void btnTest_Click(object sender, EventArgs e)
{
lblTest.Text = "hello world from btnTest_Click";
}
}
}
It should work with [WebMethod]s as well.

How to redefine a variable on content page's codebehind that was declared on master page?

I am building a web application using VS2010 and ASP.NET 4
I have managed to declare and define a variable in a nested master page and call it within the master page. However, how do I change the value of that variable from a content page's codebehind?
Here are the variable declarations from DeckNav.master.cs (nested master page codebehind):
public partial class DeckNav : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
this.mfrName = "(BRAND)";
this.modelName = "(MODEL)";
}
public string mfrName { get; set; }
public string modelName { get; set; }
}
This is how I call the 2 variables (default values) in master page (DeckNav.master):
<asp:ContentPlaceHolder ID="brandAndModel" runat="server">
<h1 class="page-header"> <%= mfrName %> <%= modelName %>
</h1>
</asp:ContentPlaceHolder>
In the content page inherited from DeckNav.master, I need to know how to change the values of the variables accordingly for each ASPX content page from the codebehind.
Example:
public partial class DeckRepair : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
mfrName = "Brand 10";
modelName = "Model 12";
}
}
The snippet above does not work. Visual Studio alerts me that "The name does not exist in the current context".
EDIT:
I declared the variables as static on the master page's codebehind to:
public partial class LeftNav : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
public static string camMfr { get; set; }
public static string camModel { get; set; }
}
... and assigned values on the content page's codebehind:
public partial class BrandModel : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
LeftNav.camMfr = "BRAND 11";
LeftNav.camModel = "MODEL 11";
}
}
I'm still having the same problem. It successfully assigns the variable the first time to "BRAND 11", but when I load another content page with its own unique values for camMfr and camModel (i.e. "BRAND 22" , "MODEL 22") it retains the original assigned value ("BRAND 11"). Keep in mind I am NOT assigning a value in the master page, only declaring it.
Try
DeckNav.mfrName = "Brand 10";
DeckNav.modelName = "Model 12";

How to access user control properties from page?

I am having problem in accessing user control properties from page.
I have usercontrol on master page with some properties,but i am unable to access them from the codebehind of the page which uses that master page.i want to set some properties of usercontrol on page load.Can anyone suggest how can i access them from page.
E.G.
User Control
ucTabSystem.ascx has following properties:
public string TabName
{
get { return _tabName; }
set { _tabName = value; }
}
public string TabUrl
{
get { return _tabUrl; }
set { _tabUrl = value; }
}
Master Page
InHouseTPAMaster.master has this user control in it.
ClaimHomePage.aspx
Uses Master page InHouseTPAMaster.master and i want to set usercontrol properties in page load of this page.
You can use two methods.
The first is by using Page.Master.FindControl('controlID'). Then you can cast it to the type of your user control. The second method is by adding a <%# MasterType VirtualPath="" TypeName=""%> tag to your aspx page. In the VirtualPath add the virtual path to the master page, and the class in the TypeName. You can then access everything with intellisense
You can try this way to set your properties...
<%# Register TagPrefix="Tab" TagName="sys" Src="ucTabSystem.ascx" %>
<tab:sys id="mysys" runat="server" TabName="xxxxx" TabUrl = "yyyy" />
You need to define a public interface with two properties - TabName and TabUrl in separate code file.
public interface IUserControl
{
string TabName{get;set;}
string TabUrl {get;set;}
}
Implements the IUserControl interface to UserControl class. For instance, I've MyUserControl and its code-behind is:
public partial class MyUserControl : System.Web.UI.UserControl , IUserControl
{
public string TabName
{
get { return ViewState["TabName"] == null ? string.Empty : ViewState["TabName"].ToString(); }
set { ViewState["TabName"]= value; }
}
public string TabUrl
{
get { return ViewState["TabUrl"] == null ? string.Empty : ViewState["TabUrl"].ToString(); }
set { ViewState["TabUrl"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Register MyUserControl in MasterPage and it has following markup in it.(master page)
<%# Register src="MyUserControl.ascx" tagname="MyUserControl" tagprefix="uc1" %>
......
<uc1:MyUserControl ID="MyUserControl1" runat="server" />
In Page_Load event (or any other) handler of aspx page (Which is a content page of said master page).
protected void Page_Load(object sender, EventArgs e)
{
IUserControl control = Master.FindControl("MyUserControl1") as IUserControl;
control.TabName = "Something";
control.TabUrl = "http://www.example.com";
}

ASP.Net c# - How do I instantiate an instance of a WebUserControl from within a App_Code class?

Aloha,
I have a custom control that I need to instantiate from within a class and add to a page. My class has a function that I pass the Page to so i have access to the controls on the page. I'm using this method to add standard ASP controls already and everything it working as expected. My problem is that the type for the custom control is know defined?
I read here to move the .cs from the control into the App_Code folder but when I do that it won't compile as it doesn't see the controls in the ascx as valid. For example I get CS0103: The name 'litTest' does not exist in the current context. So as they are partial classes I created a new empty partial class in the App_Code folder and left the control's .cs file alone.
Well it compiles this way but when I add the control to the Page.controls collection, I dont see anything on the page where it should be. For example I added TEST to the bottom of the ascx file, it I dont see it on the page. Additionally the control has variables that I need to set that I don't have access to when using the empty partial class.
I know that what I am trying to do works with standard controls, why can't I seem to make this work with a custom control?
My partial class in the App_Code folder:
public partial class CustomControlClass : System.Web.UI.UserControl
{
}
My partial class in for the user control:
public partial class CustomControlClass : System.Web.UI.UserControl
{
private int _myValue= -1;
public int myValue
{
get { return _myValue; }
set { _myValue= value; }
}
protected void Page_Init(object sender, EventArgs e)
{
litTest.Text = "TEST";
}
}
My user control ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="CustomControlClass.ascx.cs" Inherits="CustomControlClass" %>
<asp:Literal ID="litTest" runat="server"></asp:Literal>
TEST
My App_Code class:
public class MyClass
{
public static void doWork(Page Ctrl)
{
CustomControlClass c = new CustomControlClass();
//c.myValue = 1; // Wont compile with this line
Ctrl.Controls.Add(c);
Literal l = new Literal();
l.Text = "HELLO";
Ctrl.Controls.Add(l);
}
}
The page output does not have the word TEST on it at all. The word HELLO shows up just fine. I've tried calling the MyClass.doWork() from the pages Load, Init and PreInit callbacks, all result in the dame thing.
Update:
As Minh Nguyen suggested I can use Ctrl.LoadControl("~/Controls/CustomControlClass.ascx"); to load the control but I can not cast it as its own type I have to assign it as a Control type:
Control c= Ctrl.LoadControl("~/Controls/CustomControlClass.ascx");
Doing this will let me add the control to the page and have it work as expected. The down side is that I have no access to any of the controls properties. To solve this i am doing this:
c.GetType().GetProperty("myValue").SetValue(c, 1, null);
This works, but I'm not sure how expensive that it to use. I wish I could just cast the control but I get an error when I try.
I'm leaving this unanswered for a bit to see if there are any other options.
Use
CustomControlClass c = (CustomControlClass)Ctrl.LoadControl("~/VirtualPathToASCX/CustomControlClass.ascx");
instead of
CustomControlClass c = new CustomControlClass();
UPDATE: fix cast bug
//LoadControl
ASP.customcontrolclass_ascx c = (ASP.customcontrolclass_ascx)this.LoadControl("~/Controls/CustomControlClass.ascx");
//set myValue
c.myValue = 3;
you can't see ASP.customcontrolclass_ascx type in VS AutoComplete List but it compiled with no error.
not sure what's going on with your code, but using mostly what you showed works for me:
~/controls/testControl.ascx:
<%# Control Language='C#' AutoEventWireup='false'
Inherits='CustomControlClass'
%>
<asp:Literal ID='litTest' runat='server'></asp:Literal>
.aspx page:
<%# Page Language='C#' %>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<script runat='server'>
protected override void OnInit(EventArgs e) {
base.OnInit(e);
MyClass.doWork(this.Page);
}
</script>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head runat='server'><title></title></head>
<body><form id='form1' runat='server'>
</form></body></html>
~/app_code/CustomControlClass.cs:
using System;
using System.Web;
using System.Web.UI.WebControls;
public partial class CustomControlClass : System.Web.UI.UserControl {
private int _myValue= -1;
public int myValue {
get { return _myValue; }
set { _myValue= value; }
}
private Literal _litTest;
public Literal litTest {
get { return _litTest; }
set { _litTest= value; }
}
protected override void OnInit(EventArgs e) {
base.OnInit(e);
litTest.Text = "TEST";
}
}
~/app_code/MyClass:
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public class MyClass {
public static void doWork(Page Ctrl) {
CustomControlClass c =
(CustomControlClass) Ctrl.LoadControl("~/controls/testControl.ascx");
c.myValue = 1;
Ctrl.Form.Controls.Add(c);
Literal l = new Literal();
l.Text = string.Format(
"<p>CustomControlClass.myValue: {0} </p>",
c.myValue
)
+ string.Format(
"<p>CustomControlClass.litTest.Text: {0} </p>",
c.litTest.Text
)
;
Ctrl.Form.Controls.Add(l);
}
}
in other words the cast to CustomControlClass when calling LoadControl() works for me. if i understood you correctly that's the problem?
A different way of LoadControl which works (only .NET 4 tested)
Usage is as follows in any page you can call
protected void Page_Load(object sender, EventArgs e)
{
Control ctrl = SomeClass.GetNewUserControl( "hello add me");
Panel1.Controls.Add(ctrl);
}
~/app_code/BaseMyControls.cs:
using System;
using System.Collections.Generic;
using System.Web;
/// <summary>
/// Summary description for BaseMyControls
/// </summary>
public class BaseMyControls : System.Web.UI.UserControl
{
public string strProperty;
public BaseMyControls()
{
}
}
~/app_code/SomeClassInApp_Code.cs:
using System;
using System.Collections.Generic;
using System.Web;
/// <summary>
/// Summary description for SomeClassInApp_Code
/// </summary>
public class SomeClassInApp_Code
{
public static System.Web.UI.Control GetNewUserControl(string someString)
{
BaseMyControls bc = (BaseMyControls)(new System.Web.UI.UserControl()).LoadControl("~/controls/MyUC.ascx");
bc.strProperty = someString;
return bc;
}
}
~/controls/MyUC.aspx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="MyUC.ascx.cs" Inherits="MyUC" %>
<asp:Label runat="server" ID="lbl" /></asp:Label>
~/controls/MyUC.aspx.cs:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class MyUC : BaseMyControls
{
protected void Page_Load(object sender, EventArgs e)
{
string a = this.strProperty;
lbl.Text = a;
}
}

Categories