ASP.NET expose controls to other class - c#

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.

Related

The name does not exist in the current context. Not seeing class

I am very new to C# coding, so this may be very simple. In my Site.Master.cs, I have the following code:
GetLoggedInUserProperties();
lblLoginUser.Text = string.Format("Welcome {0}", Session[SessionVars.UserName]);
In a class file, I have put the following in a Public Class:
void GetLoggedInUserProperties()
{
string sLoginId = Program.ExtractUserName(HttpContext.Current.Request.ServerVariables["LOGON_USER"]);
HttpContext.Current.Session[SessionVars.LoginId] = sLoginId;
VerifyInAD(sLoginId);
}
There are no errors in the class file, but my Site.Master.cs cannot find the code in the class file.
I am sure there is a better way to do this, so feel free to let me know. Also, the lblLoginUser does not seem to work either. It has the same error. I have tried recreating the label and deleting the designer file (which never came back). Not sure if this is related or not.
Thank you.
You need to make your methods public or protected to be visible from the markup. So if you want to reference GetLoggedInUserProperties() from the markup, you'll need to change your method declaration to something like this.
protected void GetLoggedInUserProperties()
{
}
Make your method public
Here your class
public class ClassName
{
public void GetLoggedInUserProperties()
{
}
}
public MainWindow()
{
InitializeComponent();
ClassName instance = new ClassName();
instance.GetLoggedInUserProperties();
}
Or make your class static and call your method :
public static class ClassName
{
public static void GetLoggedInUserProperties()
{
}
}
public MainWindow()
{
InitializeComponent();
ClassName.GetLoggedInUserProperties();
}

Using local variable in aspx page

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";
}

C# Inconsistant Accessibility on public method (with ref)

I searched some fora and topics to look for the answer but I'm not able to find the solution for my problem. I'll post the code:
namespace Configurator
{
public partial class Dialog : Form
{
private DataStorage dataStorage = null;
public Dialog
{
InitializeComponent();
}
public void setDataStorage(ref DataStorage ds)
{
this.dataStorage = ds;
}
}
}
And it's being used in this class:
namespace Configurator
{
public partial class MainView : Form
{
private DataStorage dataStorage = new DataStorage();
private Dialog DialogBox = new Dialog();
public MainView
{
InitializeComponent();
}
private void newObjectButton_Click(object sender, EventArgs e)
{
DialogBox.Show();
DialogBox.setDataStorage(ref dataStorage);
}
}
}
This is the error:
Inconsistent accessibility: parameter type 'ref Configurator.DataStorage' is less accessible than method Configurator.Dialog.setDataStorage(ref Configurator.DataStorage)
Mark your class DataStorage with public and your error will go away :)
Your class Dialog is public. Your method setDataStorage is also public. This makes this method visible to all other assemblies. But how can other assemblies use that method if they do not have access to the parameter type DataStorage because that one is not visible (probably because it is marked private or internal.)

Im getting "an object reference is required for the non-static field" exception on non static methods... what am I doing wrong?

I have a default page and an analisis page, and at Default I have some radio buttons to change a table, but I'm getting a "an object reference is required for the non-static field" exception on compilation, everything is non-static, and I haven't figured out why I'm getting this error.
Here's the code for _Default:
public partial class _Default : System.Web.UI.Page {
public bool Carro {
get { return radCarroSi.Checked ;}
}
}
And here is the code for Analisis:
public partial class Analisis : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
_Default prevPage = PreviousPage as _Default;
if (prevPage != null) {
if (_Default.Carro == true) {
row8.Visible = false;
}
}
}
}
}
Can you help me? I believe its pretty easy but as I'm new at asp I haven't seen the problem.
Thanks in advance.
You don't have an instance of _Default:
You're just referring to the class name, not the instance of the class.
To elaborate a little further.
public class YourClass
{
public bool Carro { get; set; }
}
YourClass instance = new YourClass(); // this would create a new instance of `YourClass`.
You can refer to it by using instance.Carro like you have done with _Default.Carro
However I believe you are trying to determine if the value of Carro has been checked in the page, ASP.NET doesn't work quite like this, you will need to understand how to manage state between the client and server. This can be achieved via ViewState, Session, Cookies and Query Strings
You can't check if a radio button is checked in a different page so this line will not work in the Analisis page (besides, you don't even have an instance of _Default):
if (_Default.Carro == true) {
row8.Visible = false;
}
You need to pass the radion button value between pages using Session, Querystring or some other method

Multiple inheritance in C# - again

I know that C# does not offer multiple inheritance. And I know there' are workarounds like this one for instance.
But here's a problem that I faced today, can't figure any ELEGANT workaround. I'll add some abstract code-sample so you get it quicker...
(let it be a real-life ASP.NET code - cause those "class A, class B" code-samples are really confusing):
public class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage, JQueryPage;
Compose out the functionality? This is better for Single Responsibility. You'd have to think carefully about your constructors.
interface IAdminPage {
public string AdminPageMethod();
}
interface IJQueryPage {
public string JQueryPageMethod();
}
internal class AdminPage : IAdminpage {
private string someString;
internal AdminPage(string value) {
this.someString = value;
}
public string AdminPageMethod() {
return "AdminPage result with some string: " + this.someString;
}
}
internal JQueryPage : IJQueryPage {
private int someNumber;
internal JQueryPage(int value) {
this.someNumber = value;
}
public string JQueryPageMethod() {
return "JQueryPage result with number: " + this.someNumber;
}
}
class AdminJQueryPage : IQueryPage, IAdminpage {
private readonly IAdminPage adminPage;
private readonly IJQueryPage jqueryPage;
public AdminJQueryPage(string someString, int someNumber) {
this.adminPage = new AdminPage(someString);
this.jqueryPage = new JQueryPage(someNumber);
}
public string AdminPageMethod() {
return this.adminPage.AdminPageMethod();
}
public string JQueryPageMethod() {
return this.adminPage.JQueryPageMethod();
}
}
If you really want multiple inheritance, look at Scala's traits
Edit: added passing of constructor values to composed out classes. Also made the classes internal (cannot be accessed or constructed outside the assembly) because they are only ever constructed by the AdminJQueryPage class, which is the 'public-facing' class.
I came from C++ too and dont miss it, especially since reading Refactoring [and using a non-OOTB tool for that].
You can use PostSharp to post process based on placing attributes on your AdminJQueryPage which would achieve the exact same effect.
Or you can Extract Method code into helper classes and call that (i.e., Joe's example)
Or you can put the helpers in a single base class and call from that.
Either way your code will be clearer.
It's only a matter of time before your mixins start overlapping, and then your general suite of techniques for managing that complexity needs to kick in - in C++, MI should only have been one tool in a suite - rather than a very sexy hammer.
its possible to fake a mixin by specifying a interface and creating extension methods for that interface. however I'm not use this will help overriding methods, only adding new ones. you are of course able to then call an extension method when overriding, but that is basically the same as extracting the methods to a helper class, but with a little more sugar
Even if it was possible, one problem with the semantics of an MI-based solution to the specific problem you raised is what happens on the markup side? The Render() method that generates the markup would run first in one class, and then in the other? That's probably not the behavior you want when both classes generate entire pages.
If you're open to solutions that are outside of the language itself, there are several elegant options in ASP.NET that will address the type of issue you raised (changing the actions taken during an event in the page life cycle). For example:
Page Adapters
Control Adapters
Custom user controls
HttpModules
Master Pages
Tag mapping
The best choice will of course depend on the details of your application. In case it's helpful, I cover those options in my book, including sample code: Ultra-Fast ASP.NET.
The simplest approach is to build a hierarchy - allow AdminPage to inherit from JQueryPage like so:
public class AdminPage : JQueryPage
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage
My guess is some of this awkwardness comes from the ASP.NET page model, which uses overridden base class methods.
You can to do this with Interfaces
public interface IJQueryPage
{
}
public abstract class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
protected override void OnLoad(EventArgs e)
{
if (this is IJQueryPage)
{
RegisterJQueryScript();
}
base.OnLoad (e);
}
}
public class AdminJQueryPage : AdminPage, IJQueryPage
{
}

Categories