I have developed a server control inherited from WebControl that wraps any number of child controls and changes their output. The control class is very simple and only contains the RenderContents method.
Here is an example of how it has been placed on the page. (Not included: registration of control namespaces.) The intention here is that the rendered output from the RichImageField control will be changed:
<RX:HideWhitespaceControl runat="server">
<PublishingWebControls:RichImageField
FieldName="PublishingPageImage"
runat="server"
id="PageImage">
</PublishingWebControls:RichImageField>
</RX:HideWhitespaceControl>
However when I try to browse to the page none of the code in my control class appears to execute and I receive the following error:
Parser Error Message: Type
'RX.SharePoint.Common.Controls.HideWhitespaceControl'
does not have a public property named
'RichImageField'.
I'm confused about why this error is appearing. There is indeed no public property named RichImageField as this is not a property but rather a child control!
My custom control is being used in a SharePoint publishing site on a page layout so I'm not sure if this error is coming from SharePoint. But it looks like a basic ASP.NET error so what am I missing?
Maybe you need to add the, ParseChildren(false), PersistChildren(true) attributes to your custom control, like:
[ParseChildren(false)]
[PersistChildren(true)]
public class YourControl : WebControl
You need to override the AddParsedSubObject(object obj) method to handle child elements:
protected override void AddParsedSubObject(object obj)
{
if (obj is LiteralControl)
{
// This is pure HTML or text...
}
else if (...)
{
// Handle ASP.NET controls...
}
}
Related
The ASP.NET function ClientScript.RegisterClientScriptBlock can be used to register a chunk of JavaScript code that will be added to the page when it's rendered. The idea here is that you could have multiple instances of various user controls trying to register the same script over and over, but this ensures that it will only be included once.
The problem is, you don't really have any control over where the code is added to the page. This will insert the code inside the BODY tag of your page, but I need to add something (not limited to JavaScript code) into the HEAD block.
I'm well aware of various methods of adding something to the HEAD block via a ContentPlaceHolder block or by "Head.Controls.Add but these options do not address the problem of the same thing being added multiple times.
Is there an existing way to do this, or do I have to write a class that does something similar to ClientScript.RegisterClientScriptBlock except targeting the HEAD block?
I threw together a user control. There's nothing in the markup at all, so you can just add a new Web Forms User Control to your project and put this in the code behind:
public partial class ScriptControl : System.Web.UI.UserControl
{
private Dictionary<string, string> _scripts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public void RegisterScript(string key, string script)
{
if(!_scripts.ContainsKey(key)) _scripts.Add(key, script);
}
protected override void Render(HtmlTextWriter writer)
{
writer.WriteFullBeginTag("script");
foreach(var script in _scripts.Values) writer.Write(script);
writer.WriteEndTag("script");
}
}
Just add the directive to your page markup:
<%# Register TagPrefix="uc" TagName="ScriptControl"
Src="ScriptControl.ascx" %>
(where "ScriptControl.ascx" is whatever you've named the control)
and then you can add it wherever you need to, including in the header.
<head runat="server">
<uc:ScriptControl id="HeaderScriptControl" runat="server"/>
</head>
The usage is pretty much the same:
HeaderScriptControl.RegisterScript("myScript",
#"alert(""hello, world!"")");
I am trying to register a custom event I added to a user control.
I can do this in code behind, but not in the aspx file.
What am I doing wrong?
Thanks!
The user control:
public delegate void MemberSelectedEventHandler(object sender, string fullMemberName);
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public event MemberSelectedEventHandler OnMemberSelected;
protected void Button_OnClick(object sender, EventArgs e)
{
if (OnMemberSelected != null)
{
OnMemberSelected(this, "Peter");
}
}
}
This works (code behind of aspx page):
MyMemberControl.OnMemberSelected += new MemberSelectedEventHandler(MyMemberControl_OnMemberSelected);
But this doesn't (aspx page):
<scn:MemberControl OnMemberSelected="MemberControl_OnMemberSelected" runat="server" ID="MyMemberControl" />
In the markup you need to prefix your event property with On so the page will know to register the event. Morzel had the answer though it's not stated explicitly.
<scn:MemberControl OnOnMemberSelected="MemberControl_OnMemberSelected" runat="server" ID="MyMemberControl" />
OnOnMemberSelected should cause your handler to be invoked as expected.
First of all I have to take a bit note: When you make a custom event, you don't need to name it with 'On' prefix. .Net framework adds this prefix and the markup intellisense will show you OnOnMemberSelected.
I don't know if it needs, but try to put the delegate declaration inside your WebUserControl1 class. I always do this.
Markup intellisense reacting really slow and I don't see if it deterministic when popullates intellisense information again.
Sum of all:
- put the delegate definition into your class.
- build
- insert your markup code.
If intellisense doesn't work immediatelly I think it will works.
I am creating an object at server side of an aspx (test.cs) page from a class (asp.net 2.0 C#)
public partial class Vendor_VendorUsedTicketsPopup : System.Web.UI.Page
{
ReportInvoice _objReportInvoice = new ReportInvoice();
protected void Page_Load(object sender, EventArgs e)
{
_objReportInvoice.ReportId = 1;
}
}
as you see above before Page Load I am creating a new ReportInvoice object and on page load I am setting property ReportId to 1
On test.aspx I want to use the ReportId value bu using the _objReportInvoice object like below
<div><% _objReportInvoice.ReportId; %></div>
But when I build the site I get the error
The name '_objReport' does not exist in the current context
I know that I can create a public integer for ReportId above Page_Load and use it on aspx page. That works fine , but I want to use class object properties on aspx page.
What is the way of doing sth like that ?
Thanks...
You need a = sign in there to print it to the page:
<div><%= _objReportInvoice.ReportId; %></div>
However, I would suggest just using a Literal or Label control there and then setting it's text to the ReportID property in the code behind. Inline code like that can make your HTML messy.
Remember that your .ASPX markup page inherits from the codebehind class.
This means that unless you declare your field as protected or public, the .aspx will not have access to your field.
You need to add an access modifier to your field to make it non-private.
I have a UserControl that is working fine. It is declared like this.
public partial class DynamicList : System.Web.UI.UserControl
{
protected static BaseListController m_GenericListController = null;
public DynamicList()
{
m_GenericListController = new GenericListController(this);
}
}
Now I want to override this control so I can change some of the properties. I have created a class like this.
public partial class JobRunningList : DynamicList
{
public JobRunningList()
{
m_GenericListController = new JobListController(this);
(m_GenericListController as GenericListController).ModuleId = 14;
}
}
It appears that the controls in the DynamicList are not getting created though when I use the JobRunningList control now causing predictably bad results. The DynamicList UserControl has a ListView on it and a few other controls. It appears these are not created when using the JobRunningList. Is there any secret to this?
The boring workaround would be to make JobRunningList as plain old user control that contains a DynamicList and just sets the properties of the inner control in its OnLoad. That's awkward if DynamicList has many other properties that you want to access from the page though, as JobRunningList would have to define matching properties of its own. Getting back to the inheritance approach, then...
The DynamicList class just contains the code behind logic, so what you're doing works nicely if you want the second control to reuse the logic behind the first but provide a new UI of its own.
The markup in your .ascx file gets compiled into another class that inherits DynamicList, so if you can get your JobRunningList class to inherit that class instead of DynamicList, you'll get the result you want. This class gets a default name derived from the filename, but you can avoid guessing that by setting a ClassName in the control directive to use instead of the automatic name.
Take a simple base control like
<%# Control Language="C#" AutoEventWireup="true"
CodeFile="HelloControl.ascx.cs" Inherits="HelloControlBase"
ClassName="MyControls.HelloControl" %>
Hello <%= Name %>
with an unexciting code-behind like
public partial class HelloControlBase : System.Web.UI.UserControl
{
public string Name
{
get;
set;
}
}
Now we want to override the Name property in a new control. First we need HelloAlice.ascx
<%# Control Language="C#" AutoEventWireup="true"
CodeFile="HelloAliceControl.ascx.cs"
Inherits="HelloAliceControl" %>
Not much to see here, since we're leaving all the work to the original ascx. Now in the code-behind,
public partial class HelloAliceControl : MyControls.HelloControl
{
protected void Page_Load(object sender, EventArgs e)
{
this.Name = "Alice";
}
}
We just inherit MyControls.HelloControl and set the Name property, and it looks like we're done.
The problem is knowing when MyControls.HelloControl is visible. As long as your derived control is in the same directory as the parent control you'll probably be OK, otherwise it's quite easy to run into build errors complaining that the class doesn't exist because the parent control hasn't been compiled yet.
If I understand correctly, you want the interface to be the same. In that case, I would create some properties instead. Perhaps just a simple enumeration i.e. ListType.
I'm new to jquery and asp.net so please forgive if this is an obvious question. I'm using a jquery autocomplete plugin which requires that the page it looks up asynchronously for data is in this format as pure text only:
product1|price1
product2|price2
product3|price3
WITHOUT ANY OTHER HTML MARKUP. Any other html tags seems to cause problems.
Normally for a page like that I would use a repeater and some standard database calls and output the 2 fields. This however creates html tags.
How can I output this data as text only with no other markup whatsoever?
If you have a bare page with no master page referenced a repeater shouldn't produce any html. Make sure in the HTML view you only have:
<asp:Repeater ID="outRepeater" runat="server">
- your template here
</asp:Repeater>
An alternative would be to add a new Handler to your project which is a class that implements the IHttpHandler interface. This would allow you to output your code directly. This would end up looking like:
public class MyOutputHandler : IHttpHandler {
public bool IsReusable { return false; }
public void ProcessRequest(HttpContext context) {
context.Response.Write("product1|price1");
}
}
If you have added this to a project as a new Handler (from add items) it should have a .ashx extension. Otherwise you'll need to register it in your web.config with its type and filename.