Using aspx controls in base class - asp.net

I've got two aspx pages which are very similar and have various identical functions in the code behind. I'd like to create a base class which both the code behind classes derive from. Is it possible for the base class to access the controls on the aspx page. For instance:
class base
inherits System.Web.UI.Page
Sub prepareScreen()
'txtName is a text box on the aspx page
Me.txtName.text = "George"
end sub
end class
class codeBehind
inherits base
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
prepareScreen()
end sub
end class
Somewhat understandably the code fails to compile with:
'txtName' is not a member of 'clsbase'
Is it possible to link the two together?

You need to declare the control as a property of the base class. Then in the ASP markup, use the CodeFileBaseClass attribute.
The MSDN reference is no longer available.
class base
inherits System.Web.UI.Page
Protected Property txtName() As TextBox
Sub prepareScreen()
'txtName is a text box on the aspx page
Me.txtName.text = "George"
end sub
end class
class codeBehind
inherits base
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
prepareScreen()
end sub
end class
<%# page CodeFileBaseClass="base" inherits="codebehind" ... %>

It would be better if you refactor your code, so that you have no need to do something like this.
One better idea will be if you create a virtual method in the base class, which you can override in your child page(s), and set the value of your textbox, as you'll have an easy access to the textbox.

You could use FindControl, eg.
TextBox txtName=FindControl("txtName");
which would find the control on the rendered page even though it was rendered by the descendant class. Though this is breaking the point of OO and separation of function/data somewhat.

You can use ((TextBox)Page.FindControl("txtName")) to get the textbox. Be careful because if you use this base class else where the control might not exist

In response to your clarification:
You could Create a property:
protected TextBox txtName
{
get{return (TextBox)Page.FindControl("txtName");}
set{Page.FindControl("txtName") = vale;}
}
Or Create a Virtual property:
protected virtual TextBox txtName{get;set;}
In this case you would have to override it at your main class
protected override TextBox txtName{/*same as above*/}

Related

Programatically adding MenuItems triggers Page_load in target URL

I am adding menu items programmatically so I can control which ones appear based on the role of the user. My problem is that every menu item I add behaves as if it has been clicked on during the load. Stripped to bare bones, here is the simplified code:
Public Class test2
Inherits System.Web.UI.Page
Private Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
If Not IsPostBack Then
CreateMenu()
End If
End Sub
Private Sub CreateMenu()
MainMenu.Items.Add(New MenuItem("Home", "", "/Peak.aspx"))
End Sub
End Class
The test2.aspx contains:
<form id="form1" runat="server">
<asp:Menu ID="MainMenu" runat="server" >
<Items>
</Items>
</asp:Menu>
</form>
This is all the code in Peak.aspx.vb:
Public Class Peak
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
MsgBox("This should not appear but does!!")
End Sub
End Class
The Peak.aspx Page_Load is being loaded and the message box displayed, when test2 is set as the start up page. My real code has several menu items added and CreateMenu causes ALL the page_Loads to be being triggered with a large overhead!
Is this a bug or something I can switch off, and is there a workaround?
You're using this constructor https://msdn.microsoft.com/en-us/library/b00a9c35.aspx
public MenuItem(
string text,
string value,
string imageUrl
)
If you look at it carefully, your third parameter sets imageurl, thus triggering Page_Load event when it tries to load the url. Maybe you wanted to use this overload with 4 parameters? https://msdn.microsoft.com/en-us/library/70k2h50z.aspx
public MenuItem(
string text,
string value,
string imageUrl,
string navigateUrl
)

Why a private event handler does not work in ASP.NET

Here is the issue:
I have a simple ASP.NET form with 2 buttons.
One of them is created by dragging the button from the tools and the other I created directly in HTML:
<body>
<form id="Form1" method="post" runat="server">
<asp:Button OnClick="ABC" Runat="server" Text="rrr" id="Button1"></asp:Button>
<asp:Button id="Button2" runat="server" Text="Button"></asp:Button>
</form>
</body>
Button2 is created using tools and has the following Event Handler:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim s As String = ""
End Sub
This "Private Event handler runs without any problem.
However for the button which is created under HTML , we have the following event handler:
Private Sub ABC(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As Integer = 0
End Sub
For this one I get the following complile error:
Compiler Error Message: BC30390: 'WebApplication9.WebForm1.Private Sub ABC(sender As Object, e As System.EventArgs)' is not accessible in this context because it is 'Private'.
If I change the event handler scope from Private to protected this will work. Question is why private works for one event handler but not the other one.
Basically, an aspx page is implemented as two classes. One of these classes contains your code behind code (.aspx.vb) (and, depending on which version/model of ASP.Net you're using, also some designer generated code (.aspx.designer.vb)).
The second class is created when the page is first requested (or the site is pre-compiled) and contains any inline code from the .aspx page and other code generated by ASP.Net, and includes e.g. code for any controls declared with runat="server".
This second class inherits from the first.
So, if the first class takes responsibility for hooking up its event handlers, it uses a Handles clause*:
Private Sub ABC(...) Handles Button1.Click
Button1 belongs to this class because it was put there by the designer generated code. Everything is local to this class, and so the method can be Private.
If the second class takes responsibility for hooking up an event handler, it does it by using attributes on server controls, such as here:
<asp:Button OnClick="ABC" Runat="server"
Now, unless ABC is a method declared inline inside the .aspx file, it has to be from the first class (or any class from which the first itself inherits from)
We now have a situation where code in the second class wants to refer to code in the first class. And so, the rules of .NET say that the member that it's trying to access cannot be Private.
What you shouldn't have, as you have in your question, is both classes taking responsibility for hooking up the (same) event handlers.
*It doesn't have to use a Handles clause - it could also set up the event handler using AddHandler inside e.g. the Page_Load event, or anywhere else that's appropriate. Handles is idiomatic for static controls on a page in VB. In C#, there's no equivalent to Handles, so the event handlers are hooked up with C#'s equivalent of AddHandler, +=.

asp.net masterpage - make hyperlink visible at runtime

Is it possible to alter the visible property of hyperlinks on a masterpage at runtime?
thanks
If you expose the hyperlink as a property on the master page, you can get a reference to a pages master and cast that to your specific master page then set visibility of the hyperlinks using that property.
In your master page have something like this:
Public ReadOnly Property RemitViewerLink() As HyperLink
Get
Return hlRemitViewer
End Get
End Property
Then in your child page you can do this
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim MyMaster As MasterPage = DirectCast(Page.Master, MasterPage)
MyMaster.RemitViewerLink.CssClass = "selectedMenuItem" 'or set visibility
End Sub
No, if you set visible=False then it won't even display in the HTML output of the page. You would need to use javascript to hide/show the hyperlinks instead.

Single javascript function for multiple web pages

I have around 40 aspx pages in my website.
I want to use a javascript function which needs to be called when any of the 40 pages is loaded.
something like
I could have this function in the "head" section of each of the 40 aspx pages and then call in the body onload event. But I would like to have this function at a single place.
This is an existing app so I cannot create a master page and have all the pages derive from it.
Any ideas?
You will need to put the function in a .js file and call from your pages, but you will need to link to the script in all your 40 pages, since you can't add master page.
You can create a base class that it will be inherited by all these pages and write the logic of inserting javascript there.
So, do something like it:
Create a base class:
[Serializable]
public class RequiresFunctionBasePage : System.Web.UI.Page
{
public RequiresFunctionBasePage()
{
this.Load+= new delegate
{
this.ClientScript.RegisterClientScriptInclude("yourScript", "http://yoursite.com/yourJs.js");
this.ClientScript.RegisterStartupScript(this.GetType(),
"functionOnload", "functionName();", true);
}
}
}
And into your aspx codebehind:
public partial class yourPageNameGoesHere : RequiresFunctionBasePage
{
(...)
I suppose if you wanted to make it difficult/elegant, you could make an HttpModule that injects the script. That way it's only in one place and you can wire it up in the web.config.
Here's a sample httpModule
Public Class JavascriptInjector
Implements IHttpModule
Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler context.PreRequestHandlerExecute, AddressOf PreRequestHandlerExecute
End Sub
Private Sub PreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs)
Dim myPage = TryCast(HttpContext.Current.CurrentHandler, Page)
If myPage Is Nothing Then Exit Sub
AddHandler myPage.InitComplete, AddressOf Page_Init
End Sub
Sub Page_Init()
Dim myPage = TryCast(HttpContext.Current.CurrentHandler, Page)
If myPage Is Nothing Then Exit Sub
Dim path = myPage.ResolveUrl("~/js/jscript.js")
myPage.ClientScript.RegisterClientScriptInclude(myPage.GetType, "common", path)
End Sub
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub
End Class
Here's an entry in the web.config
<httpModules>
<add name="javascriptInjector" type="JavascriptInjector"/>
</httpModules>
You will need to modify the masterpage to include a new JS file with your new function or place your JS function in one of the JS files already included in the masterpage.
For a fully client side solution you could create a javascript file (possibly named script.js) that you link to from the head of your master page. In that file put your function.
So, the javascript in the script.js file would be something like this:
function SampleFunction(text) {
alert(text);
// or whatever code you want
}
and then in the head of your pages
<script type="text/javascript" src="script.js"></script>
and then your onload can be
onload="SampleFunction('hi there');"
have fun :)
robb

Masterpage with Asp.net Ajax problem

I placed the scritmanager to masterpage. "scriptmanager1"
There is an updatepanel in the masterpage shows total. "updatepanel1"
In the contentpage I have nested listviews. the "listview2" inside the "listview1" has itemtemplate with a linkbutton called "addtoTotal"
I want to update the updatepanel1 inside the masterpage when user clicks to addtoTotal button.
updatepanel1's update mode is conditional.
How can I do this.
Firstly I could not findcontrol addtoTotal linkbutton.
Second how can I register this button to update updatepanel1
I want to triger the conditional updatepanel from the contentpage.
I tried to do something like this
protected void Page_Load(object sender, EventArgs e) { ScriptManager1.RegisterAsyncPostBackControl(myControl);
}
I could not. Because I don't know where to write this RegisterAsyncPostBackControl code. I could not findcontrol the linkbutton. I am not sure about the way I am trying to solve this is right way.
You can put a subroutine on your master page that updates the panel and you can call it from the content page like so.
Public Partial Class _Default1
Inherits System.Web.UI.MasterPage
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Public Sub updatedpage()
updatepanel1.update()
End Sub
End Class
Public Partial Class _Default5
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
CType(Me.Master, _Default1).updatedpage()
End Sub
End Class
for finding the addtoTotal button I believe you are gonna have to do the following in the code behind
ListView listview2 = (ListView)listview1.FindControl("listview2");
LinkButton addtoTotal = (LinkButton)listview2.FindControl("addtoTotal");
you should be able to find the listview2 within the first listview and then find the LinkButton within listivew2
I'm not quite sure that I understand your question but it seems to me that this article should point you in the right direction

Resources