I've search a lot for this issue but nothing came up.
My problem is the following: I have a main view in which I want to load a user control with parameters when I click on a button but the user control won't show. The constructor of the user control is called and the parameters are set, even the page load event from the user control is called. What am i doing wrong?
Main.aspx:
<%# Page Title="Main page" Language="C#" AutoEventWireup="true" CodeBehind="Main.aspx.cs" Inherits="MainApp.Main" MasterPageFile="~/Site.master" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"></asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<%-- some other fields which i send to the user control on click --%>
<div class="col-lg-1 col-sm-12 col-md-1">
<asp:Button runat="server" CssClass="btn btn-primary" CausesValidation="false" ID="generateData" OnClick="generateData_Click" Text="View info" />
</div>
<div runat="server" id="contentDiv">
<p>No info available atm.</p>
</div>
</asp:Content>
Main.aspx.cs button click event:
protected void generateData_Click(object sender, EventArgs e)
{
UserControl1 uc = (UserControl1 )this.LoadControl(typeof(UserControl1 ), new object[] { param1, param2, param3});
contentDiv.Controls.Clear();
contentDiv.Controls.Add(uc);
}
UserControl1.aspx.cs:
public partial class UserControl1: System.Web.UI.UserControl
{
public string Param3 { get; set; }
public string Param1 { get; set; }
public string Param2 { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
public UserControl1(string param1, string param2, string param3)
{
Param1 = param1;
Param2 = param2;
Param3 = param3;
}
}
UserControl1.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl1.ascx.cs" Inherits="MainApp.UserControls.UserControl1" %>
<div>
<p style="color: red">Under construction</p>
</div>
The user control isn't visible on the main page and I don't know why.
PS: I know that i can send parameters as seen below but I don't understand why I cannot use the method described above.
UserControl1 uc = (UserControl1)this.LoadControl("~/UserControls/UserControl1.ascx");
uc.Param1 = "val1";
...
Here is the full explanation of why second method with LoadControl by type will not work: Asp.net Usercontrol LoadControl Issue.
The reason there is a difference is because in the second instance you
are bypassing the binding mechanism of the the two partial classes.
When you include the ascx control in the page as a normal declaration,
the controls declared within it (the label in your example) are
automatically instantiated by the framework as the class is
instantiated. This is a binding mechnism that reads the "front-end"
ascx file and instantiates objects in the class.
When you use LoadControl(string) - you are doing exactly the same
thing.. it uses a virtual path to get the "front-end" file and ensure
controls within it are instantiated.
However, when you use the new (to 2.0) LoadControl(type, object)
version, there is no virtual path available and it rightly so makes no
assumptions (as it cannot ensure that a type has a front end file).
Related
I'm trying to create a custom Context Menu as a user control. The code behind for this user control looks like this:
public partial class UCContextMenu : UserControl
{
private List<ContextMenuItem> m_menuItems = new List<ContextMenuItem>();
protected void Page_Load(object sender, EventArgs e)
{
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public List<ContextMenuItem> Items
{
get { return m_menuItems; }
set { m_menuItems = value; }
}
public event EventHandler Command;
}
Then, I defined the ContextMenuItem type in the same namespace as the user control (in the same file actually) which is essentially a menu item:
public class ContextMenuItem
{
public string Name { get; set; }
public string Text { get; set; }
}
The ascx page for the user control includes a repeater control which is defined like this:
<div id="contentHolder">
<ul id="ulContextMenu" style="display: none; z-index: 1000; border-width: 0.8px;
font-size: 13px;" class="ui-corner-all">
<asp:Repeater runat="server" DataSource="<%# Items %>">
<ItemTemplate>
<li><a href='#<%# DataBinder.Eval(Container.DataItem, "Name") %>'>
<%# DataBinder.Eval(Container.DataItem, "Text") %></a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
And finally to use it in a page after registering it, I have:
<uc:ContextMenu runat="server" OnCommand="SomeMethod">
<Items>
<uc:ContextMenuItem Name="SomeName" Text="SomeText" />
</Items>
</uc:ContextMenu>
Now when I run this, I get a NullReference parse error on line
<uc:ContextMenuItem Name="SomeName" Text="SomeText" />
When not running, Visual Studio also says Element 'ContextMenuItem' is not a known element. It doesn't catch the exception at runtime either so maybe that way I could look at the stack trace to see what's going on. I was just wondering if anyone has encountered similar issues like this. Any help is appreciated.
Create ContextMenuItem as a normal user control. The fact that you are defining it in the same namespace as you have emphasized doesn't help you in any way.
So, just add ContextMenuItem.ascx to your project and then register and add the control on page or other control.
for example the user control i created is a dock panel, and i want to make it to allow add others controls from aspx page.
<uc1:dockPanel ID="dockPanel1" runat="server" >
--add control to here from aspx page--
</uc1:dockPanel>
You load controls dynamically via control.add method. First get an object of user control and then use control.add property for that.
See following link for the reference.
http://msdn.microsoft.com/en-us/library/aa287574(v=vs.71).aspx
in my research i found something like this.. so we can add an inner property inside the WebUserControl, for example.. but the problem that i facing now is the control is not render inside WebUserControl, its render in the page.
HTML
<uc1:dockPanel ID="dockPanel1" runat="server">
<ContentTemplate>
<dx:ASPxButton ID="ASPxButton1" runat="server" Text="ASPxButton">
</dx:ASPxButton>
</ContentTemplate>
</uc1:dockPanel>
ASCX
[ParseChildren(true)]
public partial class dockPanel :System.Web.UI.UserControl, INamingContainer
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(dockPanel))]
public ITemplate ContentTemplate { get; set; }
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (ContentTemplate != null)
ContentTemplate.InstantiateIn(this);
}
}
I have a base usercontrol in my ASP.Net app, There are HTML markup within this usercontrol that are set to runat="server" and id's. The problem I am having is when the usercontrol is loaded, the HTML markup is being returned as null
ASP.Net C# code:
public partial class webonlinecustombase : System.Web.UI.UserControl
{
public Event Event { get; set; }
public OnlineSystemPageCustom custompage { get; set; }
public OnlineSystemPageCustom.OnlineSystemPageHdr.OnlineSystemPageModule custommodule { get; set; }
public void Page_Load(object sender, EventArgs e)
{
string typeName = custommodule.ModuleInternetFile;
inpagelink.HRef = "#" + custommodule.ModuleName.Replace(" ", "").Replace("/", "");
modtitle.InnerText = custommodule.ModuleName;
Type child = Type.GetType(typeName);
UserControl ctl = Activator.CreateInstance(child) as UserControl;
if (ctl != null)
{
this.modsection.Controls.Add(ctl);
}
}
}
Here is the HTML Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="webonlinecustombase.ascx.cs" Inherits="IPAMIntranet.IPAM_Controls.webtemplatecontrols.webonlinecustombase" %>
<a id="inpagelink" runat="server"></a>
<span id="modtitle" runat="server" style="width:100%;text-align:left">Scientific Overview</span>
<div id="modsection" runat="server" style="width:100%;">
</div>
<p>Back to Top</p>
Why is the inpagelink and modtitle being returned as null?
I have seen this happen in web applications (not web sites) when changes are made to the source (especially setting runat=server on items that were not previously runat=server), but you don't switch to the designer view.
The way that I resolve this issue is to switch to design view and dirty a property in one of the fields. This usually causes VS to update the designer code-behind file.
You can double-check this file to ensure the controls have been added. If you check it prior to doing this, you should see that they are missing.
asp.net does'n have span class, so you cant do anything in code behind with it.
use LinkButton or HyperLink instead of
the other solution is to create span or a in code, something like this
var span = new HtmlGenericControl("span");
span.InnerHtml = "From<br/>Date";
span.Attributes["class"] = "blue";
placeholder.Controls.Add(span);
hope I helped :))
i know i have seen this but cant recall the correct way of doing it... basically i have a string variable called "string clients" in my .cs file.. but i wasn't to be able to pass it to my aspx page something like
<%=clients%>
please correct me, i do not recall or not sure how to do this. (new to c#) and when i googled it.. it was not clear.. or not many of these out there.. searched as
"asp.net c# <%= %> not consistent results.. maybe because i do not know how to call these..
The field must be declared public for proper visibility from the ASPX markup. In any case, you could declare a property:
private string clients;
public string Clients { get { return clients; } }
UPDATE: It can also be declared as protected, as stated in the comments below.
Then, to call it on the ASPX side:
<%=Clients%>
Note that this won't work if you place it on a server tag attribute. For example:
<asp:Label runat="server" Text="<%=Clients%>" />
This isn't valid. This is:
<div><%=Clients%></div>
In your code behind file, have a public variable
public partial class _Default : System.Web.UI.Page
{
public string clients;
protected void Page_Load(object sender, EventArgs e)
{
// your code that at one points sets the variable
this.clients = "abc";
}
}
now in your design code, just assign that to something, like:
<div>
<p><%= clients %></p>
</div>
or even a javascript variable
<script type="text/javascript">
var clients = '<%= clients %>';
</script>
For
<%=clients%>
to work you need to have a public or protected variable clients in the code-behind.
Here is an article that explains it:
http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx
Make sure that you have compiled your *.cs file before browsing the ASPX page.
First you have to make sure the access level of the variable is protected or public. If the variable or property is private the page won't have access to it.
Code Behind
protected String Clients { get; set; }
Aspx
<span><%=Clients %> </span>
You need to declare your clients variable as public, e.g.
public string clients;
but you should probably do it as a Property, e.g.
private string clients;
public string Clients{ get{ return clients; } set {clients = value;} }
And then you can call it in your .aspx page like this:
<%=Clients%>
Variables in C# are private by default. Read more on access modifiers in C# on MSDN and properties in C# on MSDN
You can access a public/protected property using the data binding expression <%# myproperty %> as given below:
<asp:Label ID="Label1" runat="server" Text="<%#CodeBehindVarPublic %>"></asp:Label>
you should call DataBind method, otherwise it can't be evaluated.
public partial class WebForm1 : System.Web.UI.Page
{
public string CodeBehindVarPublic { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
CodeBehindVarPublic ="xyz";
//you should call the next line in case of using <%#CodeBehindVarPublic %>
DataBind();
}
}
I would create a property to access the variable, like this:
protected string Test
{
get; set;
}
And in your markup:
<%= this.Test %>
The HelloFromCsharp.aspx look like this
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="HelloFromCsharp.aspx.cs" Inherits="Test.HelloFromCsharp" %>
<!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">
<p>
<%= clients%>
</p>
</form>
</body>
</html>
And the HelloFromCsharp.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Test
{
public partial class HelloFromCsharp : System.Web.UI.Page
{
public string clients;
protected void Page_Load(object sender, EventArgs e)
{
clients = "Hello From C#";
}
}
}
I have a user control which uses objects as inner properties (some code is below).
I am having trouble with setting the attribute of the Step class programmatically, when set programmatically it is being lost across postback which would indicate something to do with Viewstate (?).
When setting the property of the Step class declaratively it's working fine.
Does anybody have any ideas of what this code be/what's causing it to lose the state across postback?
ASPX Page
<uc1:StepControl ID="StepControl1" runat="server">
<Step1 Title="1. Select your Products" Enabled="true">
<Content>
<div class="clearfix">
<div class="floatRight">
<asp:Button ID="btnGoToStep2"
runat="server"
Text="Next"
CausesValidation="false"
OnClick="btnGoToStep2_OnClick" />
</div>
</div>
</Content>
</Step1>
<Step2 Title="2. Select your Features">
<Content>
<div class="clearfix">
<div class="floatLeft">
<asp:Button ID="btnBackToStep1"
runat="server"
Text="Back"
CausesValidation="false"
OnClick="btnBackToStep1_OnClick" />
</div>
<div class="floatRight">
<asp:Button ID="btnGoToStep3"
runat="server"
Text="Next"
CausesValidation="false"
OnClick="btnGoToStep3_OnClick" />
</div>
</div>
</Content>
</Step2>
</uc1:StepControl>
ASPX code behind
protected void btnGoToStep2_OnClick(object sender, EventArgs e)
{
StepControl1.Step1.StatusText = "4 Products Selected";
}
protected void btnBackToStep1_OnClick(object sender, EventArgs e)
{
// StatusText (of Step1) gets lost at this point.
}
User control code behind
public partial class StepControl : System.Web.UI.UserControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[NotifyParentProperty(true)]
public Step Step1 { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[NotifyParentProperty(true)]
public Step Step2 { get; set; }
protected void Page_Init(object sender, EventArgs e)
{
AddSteps();
}
private void AddSteps() { }
}
[Serializable()]
[ParseChildren(true)]
[PersistChildren(false)]
public class Step
{
[PersistenceMode(PersistenceMode.Attribute)]
public string Title { get; set; }
[PersistenceMode(PersistenceMode.Attribute)]
public string Status { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateInstance(TemplateInstance.Single)]
[TemplateContainer(typeof(StepContentContainer))]
public ITemplate Content { get; set; }
public class StepContentContainer : Control, INamingContainer { }
}
I think the string you set never makes it to the ViewState. I am a bit short of terminology here (read: I do not know the terminology) but I think your attribute [PersistenceMode(PersistenceMode.Attribute)] only tells ASP.NET it should look for an attribute called "Status" in the markup (ASPX-file) and if it finds one, set the property Status to its value (actually I am wondering where exactly it is put in your example?). It does not tell anybody to put something into ViewState though.
If you would define your property Status along these lines
[PersistenceMode(PersistenceMode.Attribute)]
public string Status
{
get
{
object o = ViewState["Status"];
if(o != null) {
return (string)o;
}
return string.Empty;
}
set
{
ViewState["Status"] = value;
}
}
you should be better off.
For the rest of it I am not sure if you have to call TrackViewState() in UserControls or even override SaveViewState and LoadViewState but I do not think so. If this would be the case the following links might help:
Microsoft: Understanding ASP.NET View State
ASP.NET Forum: How to preserve ViewState in user control
It might have something to do with the order of the creation of your controls in the page. If after a postback, the controls are not created in the same order as for the first load of the page, then retreiving the viewstate willl not work for those controls.
How do you set the attribute of step programmatically?