A panel web control lets a developer put the panel on a page and define content that will appear inside the panel.
Is it possible to achieve similar functionality with a user control, where I define all my custom 'chrome' in the control, but am able to drop it on a page wherever I want and define the content inside on a per instance basis?
I think you are talking about a Templated User Control. Good luck!
Options:
1) Templated Controls as referred to by Uwe and Hanlet
2) jQuery UI library
3) ASP.NET 2.0 Web Parts
It's really tricky to implement no matter which way you go.
As Hanlet EscaƱo pointed out, this is complete possible to do. I'll show:
This is the user control markup:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TemplatedUserControl.ascx.cs" Inherits="Templated_User_Control.TemplatedUserControl" %>
<table border="1">
<tr>
<th>Head</th>
</tr>
<tr>
<td>
<asp:PlaceHolder ID="plContent" runat="server"></asp:PlaceHolder>
</td>
</tr>
<tr>
<td>Foot</td>
</tr>
</table>
This is the user control code:
using System;
using System.Web.UI;
namespace Templated_User_Control
{
public partial class TemplatedUserControl : System.Web.UI.UserControl
{
private ITemplate content_m = null;
[TemplateContainer(typeof(ContentContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Content
{
get
{
return content_m;
}
set
{
content_m = value;
}
}
void Page_Init()
{
if (content_m != null)
{
ContentContainer container = new ContentContainer();
//This is the real magic. Take the contents, and put it in our ContentContainer object, then
//add the ContentContainer object as a child control of the placeholder so it renders inside the user control
content_m.InstantiateIn(container);
this.plContent.Controls.Add(container);
}
}
protected void Page_Load(object sender, EventArgs e) {}
public class ContentContainer : Control, INamingContainer {}
}
}
This is the page markup:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Templated_User_Control.Default" %>
<%# Register src="TemplatedUserControl.ascx" tagname="TemplatedUserControl" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:TemplatedUserControl ID="TemplatedUserControl1" runat="server">
<Content>
Template user control test.<br />
<asp:Literal ID="litTest" runat="server">this is a test!</asp:Literal><br />
abc 123!
</Content>
</uc1:TemplatedUserControl>
</div>
</form>
</body>
</html>
Yes, this is completely possible.
Here is a great example where a developer overrides an existing control (I chose an article with a Panel, since you used it as an example) and still allows content within.
The article is good, but you may find the sample code even more helpful.
Related
how to set or get html elements inner text or html controls value in Razor syntax.
i know how we can do this in aspx file using Runat="server" attribute like this
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><%Response.Write(Page.Title); %></title>
<script runat="server">
protected void Button1_ServerClick(object sender, EventArgs e)
{
p1.InnerText = "Hello " + textbox1.Value; //get textbox value and set in html p tag
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="text" id="textbox1" runat="server" /><br />
<input type="button" id="btn" runat="server" value="Click Me" onserverclick="Button1_ServerClick" />
<p id="p1" runat="server">see result here</p>
</div>
</form>
</body>
</html>
Basically something like this...
View (SomeAction.cshtml):
...
<p>ViewBag.SomeValue</p>
...
Controller:
...
[HttpGet]
public ActionResult SomeAction()
{
ViewBag.SomeValue = "Hello";
return View();
}
...
However you should learn much about approach which is used to build applications using ASP.MVC. It's completely different than ASP.NET WebForms. WebForms technology uses events while ASP.MVC uses Model View Controller. You have to change your mindset.
I am new to ASP.NET (and web development in general).
For some reason, in my ASP.NET master page, the hyperlink web controls are not working.
I want them as web controls so I can change the "Login" hyperlink text to "Log out" (as well as its navigateURL) if the user session is currently logged in.
Could anyone find the problem?
Here is the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
<title></title>
<link href="~/Styles/default.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
<style type="text/css">
.style1
{
width: 468px;
}
</style>
</head>
<body>
<form id="Form1" runat="server">
<div id="wrapper" runat="server">
<div id="header" class="container" runat="server">
<table style="width: 100%; height: 128px;" runat="server">
<tr>
<td class="style1" runat="server">
WEBLINK
</td>
<td>
<asp:HyperLink ID="HyperLink1" runat="server">About</asp:HyperLink>
</td>
<td>
<asp:HyperLink ID="HyperLink2" runat="server"
NavigateUrl="~/InterestPages/InterestNews.aspx">Interests</asp:HyperLink>
</td>
<td>
<asp:HyperLink ID="HyperLink3" runat="server">Blogs</asp:HyperLink>
</td>
<td>
<asp:HyperLink ID="loginLink" runat="server" NavigateUrl="~/Account/Login.aspx"
ViewStateMode="Enabled">Login</asp:HyperLink>
</td>
</tr>
</table>
</div>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</form>
</body>
Here is my C# master page code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class SiteMaster : System.Web.UI.MasterPage
{
private void Page_PreInit(object sender, EventArgs e)
{
if (Session["LoggedIn"] != null && (bool)Session["LoggedIn"] == true)
{
MasterPageFile = "~/LoggedIn.master";
}
else
{
MasterPageFile = "~/Site.master";
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (Session["LoggedIn"] != null && (bool)Session["LoggedIn"] == true)
{
loginLink.Text = "Log out";
loginLink.NavigateUrl = "";
}
else
{
loginLink.Enabled = true;
loginLink.Text = "Login";
loginLink.NavigateUrl = "~/Account/Login.aspx";
}
}
}
Why not just replace your login menu link with the asp LoginView control?
You can add an Anonymous template with your login link to point to your login page, and
a LoggedIn template with your logout link by adding the LoginStatus.
It let's you provide a welcome to the logged user.
Oh, and it also let's you get rid of all that preinit stuff and session tracking.
You can use the user identity isAuthenticated to determine if that session is logged in.
And if you want to use a different master page for your login page ... you can just create one for your login page or point it to another master page.
I also don't think your pre-init is firing.
You have empty NavigateUrl when session is not null . So please change this line loginLink.NavigateUrl = "#";
try this code
if (Session["LoggedIn"] != null && (bool)Session["LoggedIn"] == true)
{
loginLink.Text = "Log out";
loginLink.NavigateUrl = "#";
}
else
{
loginLink.Enabled = true;
loginLink.Text = "Login";
loginLink.NavigateUrl = "~/Account/Login.aspx";
}
I am trying to get the name (value) from a login view status contraol when a user in logged into my asp.net website. I want to put this value or login name into a textbox when the page loads.
Any help would be greatly appreciated.
Marlon Gowdie
Assuming the user has been authenticated then you can get the current user from the User property of the current Page. More than likely this is what the LoginView control is using internally to get the current user information.
here is simple example how to get the login name using login status control...
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Login1_LoggedIn(object sender, EventArgs e)
{
string name = Login1.UserName;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Login ID="Login1" runat="server" OnLoggedIn="Login1_LoggedIn">
</asp:Login>
</div>
</form>
</body>
I often have an issue with compile errors when I copy over an aspx page and code behind file from another project, it seems to work when I create another page and the content manually but if I just copy the files it won't. I have checked to make sure namespaces and references are ok but still doesn't make any sense. The error I get is:
Error The name 'txtUser' does not exist in the current context
I just wanted to understand why.
For e.g. I copied over the following:
ASPX
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="Login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Login</title>
</head>
<body>
<form id="form1" runat="server">
<table align="center" width="300px" style="margin-top: 200px;">
<tr>
<td>
<legend>Login</legend>
<table style="width: 30%;" align="center">
<tr>
<td>
<asp:TextBox ID="txtUser" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>
ASPX.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
txtUser.Text = "text";
}
}
This is probably because the designer file is missing for the page. If it is, you can create it manually by right-clicking the page in the solution explorer and selecting 'Convert to Web Application'.
Are you copying the login.aspx.designer.cs. This file contains a partial class that holds the definition of the controls on the .aspx page.
e.g. for txtUser you'd have the declaration in the .designer.cs file.
One thing to check is if your new project has the same Project References as the old one.
If something is missing there (or indeed in your web.config references), VS can skip generating the designer.cs file altogether, resulting in the error you mention.
As far I look to u r posted questions and the code u copy :
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="Login" %>
You get this error because in u r designer page there is no textbox control
so it throws this error :
"Error The name 'txtUser' does not exist in the current context"
For more help can you paste the exact code u r coping.
Say I have this repeater which makes use of a public function called Test in the code-behind.
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("MyCol1")%></td>
<td><%# Eval("MyCol2")%></td>
<td><%# Test((int)Eval("MyCol1"))%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
In my code-behind, I have this function
public string Test (int Value)
{
return "Test"+Value.ToString();
}
This works fine but in my website I will have similar repeaters on various pages and most of them will need to call the Test function. Instead of having it in the code-behind of each web page would it be possible to put it in a public static class and call it directly from the repeater? Something like this (which does not work):
<td><%# MyStaticClass.Test((int)Eval("MyCol1"))%></td>
The only solution I've come up with would be to change the function in the code-behind to:
public string Test (int Value)
{
return MyStaticClass.Test(Value);
}
But it would be neater if I didn't have to put any code in the code-behind of each webpage (ie I would prefer the repeater to call the static function directly).
Any ideas or suggestions?
Create a Base class for your pages and put your common function there. So it will be available for all inherited child pages.
Can't
<td><%# Test((int)Eval("MyCol1"))%></td>
Be represented by
<td><%# Eval("MyCol1", "Test: {0}") %></td>
Or is there more to your test function that that?
I typically create a class for shared/static functions in my websites. This class can then be called from any page in the site and allows the code to be seperated from your UI or presentation code.
clsGlobal.cs
namespace testClass
{
public class clsGlobal
{
public static int EvalNumber(int value){
int localInt = 5;
return localInt + value;
}
}
}
Default.aspx
Option 1
This version imports the namespace of the global class into the aspx page so you can reference your static functions without using the namespace. "clsGlobal.EvelMethod()"
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="testClass._Default" %>
<%# Import Namespace="testClass" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Static Class Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= clsGlobal.EvalNumber(5).ToString() %>
</div>
</form>
</body>
</html>
Default.aspx
Option 2
This version calls the static function using the fully qualified function name including the namespace. "testClass.clsGlobal.EvalNumber()"
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="testClass._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Static Class Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= testClass.clsGlobal.EvalNumber(5).ToString() %>
</div>
</form>
</body>
</html>
Do you use a master page? You could drop it in there if you do.
I would do something like this:
On every content page that inherits from the master page you need:
<%# MasterType VirtualPath="[path to your master page]" %>
This allows you to get to the public methods on the master.
On your content page, whenever you need to call the Test method:
Master.Test([your int value]);
The accepted answer, and other answers here, suggest that inheritance is necessary to solve this problem. This confused me, so I asked my own question - How to call functions in a Class file, when inside a Repeater, without inheritance - and thanks to #Walsharoo I found out I merely needed to add the Project Name and I could call a static function (in a Class) from inside a repeater:
<td><%# [ProjectName].ClassName.MyStaticFunction(Eval("MyColumnName"))%></td>
This may prove helpful to others, I hope, though I'm not suggesting you're all as daft as me for forgetting this simple trick.