is that possible to add controls into WebUserControl from aspx page? - c#

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

Related

User control loaded dynamically with parameters not showing in asp.net

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).

NullReferenceException when defining a custom object in ASPX

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.

How do you put custom markup in a sitecore sc field?

I need to add some custom markup for the sc:Image field to enchance SEO. This markup is not a property of the field, so from codebehind, I tried something like this:
slideImage.Attributes.Add("ControlType", "C4Image");
slideImage.Attributes.Add("rel", relString);
But this isn't working, and I see nothing in the rendered output. Is there any way to do this?
You need to use the "Parameters" property for setting extra properties on both the and control.
You can to it like this :
<sc:FieldRenderer ID="PageImage" runat="server" FieldName="ContentImage" Parameters="ControlType=C4Image&rel=relString" />
<sc:Image ID="SCPageImage" runat="server" Field="ContentImage" Parameters="ControlType=C4Image&rel=relString" />
That will be rendered like this :
<img width="1232" height="637" controltype="C4Image" rel="relString" alt="" src="~/media/Images/DEMO backgrounds/background2.ashx">
You can create you own class inheriting from the Sitecore.Web.UI.WebControls.Image and override it like this:
namespace My.Assembly.Namespace
{
public class MyImage : Sitecore.Web.UI.WebControls.Image
{
public virtual string RelAttribute { get; set; }
protected override void PopulateParameters(Sitecore.Collections.SafeDictionary<string> parameters)
{
base.PopulateParameters(parameters);
if (!String.IsNullOrEmpty(RelAttribute))
{
parameters.Add("rel", RelAttribute);
}
}
}
}
And then register the namespace and use the MyImage class:
<%# Register tagPrefix="my" namespace="My.Assembly.Namespace" assembly="My.Assembly" %>
<my:MyImage runat="server" RelAttribute="reltest" Field="logo"/>
You can use all the standard attributes from sc:Image on the my:MyImage as well.
The code will generate img tag with rel <img rel="reltest" src="logo.jpg" ... />.
You can easily extend the code above to support ControlType attribute as well.
For screnario's like this, I'd ditch the FieldRenderers and revert to a regular html tag with databinding to the (the url of the) image.
The LinkManager is your friend here.

Dynamic user control controls are null on load

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 :))

Usercontrol losing Viewstate across Postback

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?

Categories

Resources