I want to create a user control DerivedUserControl.ascx that derives form another user control BaseUserControl.ascx. The base user control derives from System.Web.UI.UserControl as required. These user controls are defined in different folders. Because I'm using a Visual Studio 2010 Web Site project (I'm not able to switch to Web Application project), these user controls are not defined inside a namespace.
My problem is that when I try to compile the project the base class of the derived user control cannot be resolved (obviously because the compiler doesn't know what .ascx file defines the base class). Is there a way resolve this issue?
I tried everything I could imagine, without success. Any help would be greatly appreciated.
BaseUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="BaseUserControl.ascx.cs" Inherits="BaseUserControl" %>
BaseUserControl.ascx.cs
public partial class BaseUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
DerivedUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="DerivedUserControl.ascx.cs" Inherits="DerivedUserControl" %>
DerivedUserControl.ascx.cs
public partial class DerivedUserControl : BaseUserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
Error
The type or namespace name 'BaseUserControl' could not be found
When using ASP.NET Web Site (as apposed to a Web Project) you need to add <#Reference> element to your DerivedUserControl.ascx.
From MSDN it...
Indicates that another user control, page source file, or arbitrary
file located at some virtual path should be dynamically compiled and
linked against the current ASP.NET file (Web page, user control, or
master page) in which this directive is declared.
<%# Reference VirtualPath="~/FolderName1/BaseUserControl.ascx" %>
Once you've done that you can reference it like so
public partial class DerivedUserControl : ASP.foldername1.baseusercontrol_ascx
Where FolderName1 is the folder your BaseUserControl is in.
Create a regular class/.cs for your base class called BaseUserControl.cs:
public class BaseUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
The problem appears to be that the DerivedUserControl.ascx does not have access to the DLL that contains the BaseUserControl. Make sure that you add a reference to the dll and have copy local = true.
This does not compile:
namespace MyBase
{
public class BaseUserControl : System.Web.UI.UserControl
{ }
}
public class DerivedUserControl : BaseUserControl
{ }
This does compile:
namespace MyBase
{
public class BaseUserControl : System.Web.UI.UserControl
{ }
}
public class DerivedUserControl :MyBase.BaseUserControl
{ }
So pretty much add the name of the namespace + dot + the name of your base class.
Good luck!
Related
I am new to c#.
Is it possible to use a local variable (declared in Page_Load method inside System.Web.UI.Page class) in the .aspx page. or do i have to declare an accessor variable inside "UI.Page" class and use it as reference?
public partial class consoleTours : System.Web.UI.Page
{
public string AStr{ get; set; }// i could use this
}
protected void Page_Load(object sender, EventArgs e)
{
string LStr=""; <i>// i couldn't use this
}
Thank you for edit. as to c# i am also new to stackoverflow as you could see.
Point of my question is.I couldn't use public property (AStr) for tryParse.i first use local variable for parsing then assign LStr to AStr and use it in the page. so it makes me use 2 variables instead one. I thought there should be another way.
You have 2 valid options 1:
Use a public property on the page:
This is what you have done already:
public class MyPage : System.Web.UI.Page
{
public string MyPageTitle { get; set; }
}
Now, the property MyPageTitle can be accessed anywhere in your cs file, and can be used in your ASPX file aswell.
If you want to have a property which is accessible on multiple pages, you must play with inheritance:
Use inheritance to create a new Page object:
First, you create class that acts as a Page:
public class ParentPage : System.Web.UI.Page
{
public string MyPageTitle { get; set; }
}
Now, when you create a new page, your code will look by default like this:
public class MyPage : System.Web.UI.Page
{
}
Change the System.Web.UI.Page to your created ParentPage, so it will looks like the following:
public class MyPage : ParentPage
{
}
Now, in the 'MyPage' class, you will have access to the MyPageTitle property as well as on the aspx file.
Thus, your are exposing a variable to another control by using inheritance.
Declare the variable just inside the class and outside of a method
public string LStr="";
protected void Page_Load(object sender, EventArgs e)
{
LStr= "this new value";
}
I am trying to modify an existing .net "website" project by adding a new class to it. I added my class inside the App_Code folder (let's call this class "ClassA"), and tried to access it from the outside in an aspx.cs file. For some reason, right after I created the class, I can create an instance of it in my aspx.cs file without any warnings from Visual Studio (e.g., ClassA a = new ClassA()). But every time I rebuild the project, I get the following Error from visual studio (The type or namespace name 'ClassA' could not be found (are you missing a using directive or an assembly reference?)). What am I missing here?
Code for Class A -> App_Code/ClassA.cs
public class ClassA
{
public string test;
}
Code for Test.aspx.cs
namespace A{
public class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ClassA a = new ClassA(); // line with error
}
}
}
If I put everything in Test.aspx.cs I get no errors:
namespace A{
public class ClassA
{
public string test;
}
public class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ClassA a = new ClassA(); // no error!
}
}
}
By default the classes inside App_Code folder has property "Build Action" set as "Content".
If you want to use it you need to set its "Build Action" property to "Compile".
This should work.
I am really sorry, for I could not totally understand the problem.
In my opinion you should not use namespaces when you create a class in app_code and let it be accessible to the whole website project.
In this instance you have added a namespace, try adding:
using b;
where b is your namespace you used in your new class. This should solve your problem.
I have been battling this for some time and I need some guidance.
I'm coding in ASP.NET 4.0 WEBFORMS.
Question is: How to expose a textbox, Label or any other control to another class.
I have a webform (see below).
public partial class WebForm1 : System.Web.UI.Page
{
}
This is then referenced and sent to another class.
public class SearchInitializer
{
private WebForm1 _webform1;
public SearchInitializer(WebForm1 Webform1)
{
_webform1 = Webform1;
}
public void ChewSettings()
{
_webform1 //can't find any control in here?!
}
}
First I thought of creating a public property which I thought I could access from the reference I sent to the new class.. But nooo!
public partial class WebForm1 : System.Web.UI.Page
{
public string KeywordBox1
{
get {return txt_keyword.Text;}
set {txt_keyword.Text = value;}
}
}
The I tried to inherit the Webform into the other class. Making the the property available but no luck there.
public class SearchInitializer : Webform1
{
private WebForm1 _webform1;
public SearchInitializer(WebForm1 Webform1)
{
_webform1 = Webform1;
}
public void ChewSettings()
{
_webform1 //can't find any control in here?!
}
}
Okay an abstract class migth be of use here, inheriting everything. But I think I got that wrong to. I have events and static classes, so they can talk with the page. But I really would like not to use a static class as a container to save all the info in my controls.
So these are the examples I have tried and they all failed. So this is me basicly trying to expand what I know ;) Thanks for reading!!
Why have they failed and how should I do it?
EDIT AS REQUESTED!
public partial class WebForm1 : System.Web.UI.Page
{
protected void btn_click(object sender, EventArgs e)
{
SearchInitializer searchIni = new SearchInitializer(this);
}
}
To expose the controls there are two methods I can think of that you can employ.
You can remove the following statement from the myPage.designer.cs file and place it in your code behind as a public declaration:
protected global::System.Web.UI.WebControls.TextBox myTextBox;
becomes
public System.Web.UI.WebControls.TextBox myTextBox;
This should make it immediately accessible. My preferred method is to add a property for each specific control that you want to provide access to.
public System.Web.UI.WebControls.TextBox MyTextBoxElement
{
get
{
return myTextBox;
}
}
This allows to provide supplementary access controls if you need them or other conditionals. In any case, to access either the field or the property, the consuming object must reference this by your specific page type.
Not sure what you are trying to do, but to access a base class within an inherited calss you need to use the base keyword, not declare an instance there of.
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string KeywordBox1
{
get { return txt_keyword.Text; }
set { txt_keyword.Text = value; }
}
}
public class SearchInitializer : WebForm1
{
public SearchInitializer()
{
}
public void ChewSettings()
{
// Works
base.KeywordBox1 = "Red";
}
}
If intellisense is not showing the property, try rebuilding the solution. It will then refresh the list of available properties and it should show.
Your original approach must work. I suggest you create a small test project with a form with text box and SearchInitializer class and see that it works, after that figure out what is different in your current project.
We are using asp .Net with C#. I have page(.aspx) consist of multiple Web User Controls(.ascx)
I would like to have an error handling machanism in such a way that if there is any exception in one of the user control, asp .net should show some friendly error message on a control. All other control should render as expected.
Is there any way this can be done without putting place holder on each control which you show/hide in case of exception?
You could do something like this.
An abstract base class with an abstract OnLoad() that each UserControl has to implement. You can use this same model for any event that you want to have shared error handling.
public abstract class BaseUserControl : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
OnLoad();
}
catch (Exception)
{
//Custom error handling here
}
}
protected abstract void OnLoad();
}
public class MyUserControl: BaseUserControl
{
protected override void OnLoad()
{
//My normal load event handling here
}
}
1) In app_code, create a class MyPage.cs that inherits Page
class MyPage : Page { }
2) Change the inherits of your pages to MyPage.
public partial class _Default : MyPage { ...
There's an attribute in the web.config you can use to change it if you want
3) Back to MyPage.cs, add the generic error handler of all pages
protected override void OnError(EventArgs e)
{
/* here you can intercept the error and show the controls that you want */
base.OnError(e);
}
First create a base user controlclass which overrides default onerror event.
public class MyControlClass:UserControl
{
protected override void OnError(EventArgs e)
{
//here you sould add your friendly msg implementation
//base.OnError(e); here should remain commented
}
}
Then you can create your user controls:
public class Control1:MyControlClass
{
// ....
// ....
}
So, if any control creates an exception , the rest will keep on working.
Just as the subject asks.
EDIT 1
Maybe it's possible sometime while the request is being processed to store a reference to the parent page in the user control?
this.Page
or from just about anywhere:
Page page = HttpContext.Current.Handler as Page
I cannot think of any good reason for a user control to know anything about the page it is on as the user control should be ignorant of its context and behave predictably regardless of what page it is on.
That being said, you can use this.Page.
you can use the Parent property
if you need this to find a control on the page then you can use
Label lbl_Test = (Label)Parent.FindControl("lbl_Test");
I always used this.Page in the System.Web.UI.UserControl.
Or you can always do a recursive call on the Parent until u encounter an object that is a Page.
kind of overkill though...
protected Page GetParentPage( Control control )
{
if (this.Parent is Page)
return (Page)this.Parent;
return GetParentPage(this.Parent);
}
I found the way to do this is to create an interface, implement that interface, use this.Page to get the page from the control, cast it to the interface, then call the method.
You must use NamingContainer like that:
try
{
if (!string.IsNullOrWhiteSpace(TargetCtrlID))
{
var ctrl = NamingContainer.FindControl(TargetCtrlID);
if(ctrl != null)
Console.Write("'" + ctrl.ClientID + "'");
}
}
catch
{
}
Every control has a parent property that you can use to access the parent.
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(this.Parent.ID);
}
EDIT:
depends on which one of the lifecycle events of the page you want to store the reference and what use to store that reference. However the reference is always available
Create a delegate in the user control and then assign it a method from the parent page.
class MyUserControl : UserControl
{
delegate object MyDelegate(object arg1, object arg2, object argN);
public MyDelegate MyPageMethod;
public void InvokeDelegate(object arg1, object arg2, object argN)
{
if(MyDelegate != null)
MyDelegate(arg1, arg2, argN); //Or you can leave it without the check
//so it can throw an exception at you.
}
}
class MyPageUsingControl : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
MyUserContorlInstance.MyPageMethod = PageMethod;
}
public object PageMethod(object arg1, object arg2, object argN)
{
//The actions I want
}
}
Writing to Page and Master Page from Web User Control:
Personally I like the user controls to be loose, but it can be done like this.
Master Page:
public partial class Second : System.Web.UI.MasterPage
{
public void SecondMasterString(string text)
{
MasterOut.Text += text;
}
}
Directive needed on WebForm1 : So page can write to master page
<%# MasterType VirtualPath="~/DemoFolder/MasterPages/Second.master" %>
Methods write to page and Master Page:
public partial class WebForm1 : System.Web.UI.Page
{
public void SetPageOutput(string text)
{
// writes to page
this.PageOut.Text = text;
}
public void SetMaster(string text)
{
// writes to Master Page
this.Master.SecondMasterString(text);
}
}
User Control writes to both Page and Master Page:
public partial class WebUserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
LegoLand.DemoFolder.MasterPages.WebForm1 page = (WebForm1)this.Parent.Page;
page.SetMaster("** From the control to the master");
page.SetPageOutput("From the control to the page");
}
}