Dynamically generated ASP.NET page hasn't basic html structure - c#

i wrote a page (only class that derives from System.Web.UI.Page, that i want to use in more websites. I dynamically add webcontrols to Page.Controls collection like this:
Panel p = new Panel();
p.Style.Add("float", "left");
p.Controls.Add(locLT);
Page.Controls.Add(p);
this code renders only
<div style="float:left;">
</div>
How can i add HTML, HEADER and BODY section without manually write this? Is it possible?

I recommend MasterPages but you can do this:
public class CustomBase : System.Web.UI.Page
{
protected override void Render( System.Web.UI.HtmlTextWriter textWriter )
{
using (System.IO.StringWriter stringWriter = new System.IO.StringWriter())
{
using (HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter))
{
LiteralControl header =new LiteralControl();
header.Text = RenderHeader(); // implement HTML HEAD BODY...etc
LiteralControl footer = new LiteralControl();
footer.Text = RenderFooter(); // implement CLOSE BODY HTML...etc
this.Controls.AddAt(0, header); //top
this.Controls.Add(footer); //bottom
base.Render(htmlWriter);
}
}
textWriter.Write(stringWriter.ToString());
}
}

I don't believe there is any way to automatically generate the tags, but you can create your own Render method that outputs the required basic HTML framework.

Before using MasterPages a common way to add header and footer for a page was to inherit from a BasePage like http://gist.github.com/214437 and from the BasePage load header and footer controls. I think that a MasterPage is better choice for you than the BasePage above. One of the drawbacks with a MasterPage is that you have to add asp:content at every page but it's still better than the old way.

If your "page" is completely dynamic and has no aspx front-end (I didn't realize this was possible?!)... then what you really want is probably a custom HttpHandler rather than inheriting from Page.

Related

ASP.NET Generic UserControl with Html Content Placeholder

This question might have already been asked, but I could not find any references to it so I apologize if it seems like a duplicate question.
What I'm trying to do is create a generic DialogBox as an ASP.NET UserControl; which would contain all the script required to create the dialog using jQuery. The dialog has a fixed set of buttons, but I'd like to be able to let the user define the content when they create the dialog. Suppose this is the markup for the user control:
<head>
<script type="text/javascript">
// jQuery script to create the dialog
</script>
</head>
<body>
<div runat="server" id="divContainer">
<!--Html Content Placeholder. What goes here?-->
</div>
</body>
And the code-behind:
[ParseChildren(true, "Contents")]
public partial class UCDialogBox : ExtendedUserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
public List<Control> Contents { get; set; }
public DialogType Type { get; set; }
public string Title { get; set; }
}
And on the actual page after registering the control, I would like to be able to do something like this:
<uc:DialogBox runat="server">
<div>
<label>Hello World</label>
</div>
</uc:DialogBox>
The problem with this is, List<Control> only allows for ASP.NET controls. Normal HTML controls (such as what I have above) won't work.
Question 1: What type should I use to allow any HTML control to be nested inside the user control? I tried System.Web.UI.HtmlControls.HtmlControl but that didn't work either (ASP.NET says The element 'div' cannot be nested within the element 'dialogbox').
Question 2 What would I put as an HTML content placeholder on the user control which can be bound to the Contents property on the code behind? Something like
<SomePlaceholderControl DataSource="<%# Contents %>" />
Any help is appreciated.
Oddly enough, putting HTML controls inside the body of the user control doesn't cause a run-time error. In fact, the controls come across just fine. I guess it's just the designer that whines about it.
As for the placeholder, I didn't have to use any specific control; I simply used an HtmlTextWriter to render the controls into a well-formatted HTML string inside a method that gets called in the markup:
<div runat="server" id="divContainer">
<%# RenderContents() %>
</div>
And the code-behind method:
public string RenderContents()
{
StringWriter writer = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
foreach (var control in Contents)
{
control.RenderControl(htmlWriter);
}
return writer.ToString();
}
It works just fine.
I am not sure whether this is the correct approach, I have added a ITemplate inside the Dialog control and placed a HtmlGenericControl container which is Div control with runat = "server".
Now you can add the html controls and text inside this container.
<cc1:UCDialogBox ID="dialog" runat="server">
<HtmlPlaceHolder>
<div runat="server">
<h1>Title</h1>
<h2>Description</h2>
<div>Modal Content</div>
</div>
</HtmlPlaceHolder>
</cc1:UCDialogBox>
In custom server control you can get the container div content as innerHtml or innerText
public class UCDialogBox : WebControl, INamingContainer
{
private ITemplate htmlPlaceHolder = null;
[
Browsable(false),
DefaultValue(null),
Description("Add your html contorls"),
PersistenceMode(PersistenceMode.InnerProperty)
]
public virtual ITemplate HtmlPlaceHolder
{
get
{
return htmlPlaceHolder;
}
set
{
htmlPlaceHolder = value;
}
}
protected override void Render(HtmlTextWriter output)
{
HtmlGenericControl placeholder = new HtmlGenericControl();
htmlPlaceHolder.InstantiateIn(placeholder);
var html = placeholder.Controls[1] as System.Web.UI.HtmlControls.HtmlGenericControl;
var result = html.InnerHtml.Replace("\r", "").Replace("\n", "").Trim();
output.Write(result);
}
}

How can I inject inline styling into a Document being loaded in my WPF WebBrowser?

I've been trying to use mshtml to modify a third party web api. Right now I am trying to change the display property on two elements to none so they will be invisible.
I know their id's.
The first one is an img and the id is zendbox_close. The second is a div and the id is zenbox_scrim.
The html looks like this
<div class="zenbox_header">
<img id="zenbox_close"></img>
</div>
...
<div id="zenbox_scrim...></div>
All I want to do is add in some inline styling so it looks like this
<div class="zenbox_header">
<img id="zenbox_close" style="display:none;"></img>
</div>
...
<div id="zenbox_scrim style="display:none;"...></div>
In my code behind for the WPF WebBrowser that is opening up the webpage, I have gotten this far:
IHTMLDocument3 doc = (IHTMLDocument3)this._browser.Document;
IHTMLImgElement element = (IHTMLImgElement)doc.getElementById("zenbox_close");
I saw in another post someone was talking about injecting scripts and they said you can use
IHTMLElement scriptEl = doc.CreateElement("script");
I am not sure what the HTML element analog to this would be though. Also I had to use IHTMLDocument3 to use the method getElementById, but that class doesn't appear to contain anything similar to CreateElement().
My question is how can I inject inline styling into a Document being loaded in my WPF WebBrowser?
Yes you can manipulate styles inline.
A good way to do this is to work with the IHTMLStyle or IHTMLCurrentStyle interfaces when working with an IHTMLElement. There are some differences with the values reflected by those two and they are not always synch'd. A better explanation of why that is:
IHTMLStyle vs IHTMLCurrentStyle
Code sample would look like:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
wb.LoadCompleted += wb_LoadCompleted;
wb.Source = new Uri("http://www.google.com");
}
void wb_LoadCompleted(object sender, NavigationEventArgs e)
{
var doc = wb.Document as HTMLDocument;
var collection = doc.getElementsByTagName("input");
foreach (IHTMLElement input in collection)
{
dynamic currentStyle = (input as IHTMLElement2).currentStyle.getAttribute("backgroundColor");
input.style.setAttribute("backgroundColor", "red");
}
}
}

Ghost cell in IE9 with Repeater Control

IE9 Generate blank cell or you can say Ghost Cell, with ASP.Net Repeater control.
I try javascript regural expression. Render function to run reg. exp. but the page holds few update controls and generate error.
Error: sys.webforms.pagerequestmanagerservererrorexception the message
received from the server could not be parsed. ScriptResource.axd
I try all the well known links for this error.
Please suggest me if you really have...
Thank You
protected override void Render(HtmlTextWriter writer)
{
using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new System.IO.StringWriter()))
{
base.Render(htmlwriter);
string html = htmlwriter.InnerWriter.ToString();
if ((ConfigurationManager.AppSettings.Get("RemoveWhitespace") + string.Empty).Equals("true", StringComparison.OrdinalIgnoreCase))
{
//html = Regex.Replace(html, #"(?<=[^])\t{2,}|(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,11}(?=[<])|(?=[\n])\s{2,}", string.Empty);
html = Regex.Replace(html, #"(?<=<td[^>]*>)(?>\s+)(?!<table)|(?<!</table>\s*)\s+(?=</td>)", string.Empty);
html = html.Replace(";\n", ";");
}
writer.Write(html.Trim());
}
another Solution is, but fail for Repeater
var expr = new RegExp('>[ \t\r\n\v\f]*<', 'g');
document.body.innerHTML = document.body.innerHTML.replace(expr, '><');
You can access the Repeater control directly (before it's written to the page and rendered by IE) and remove the cells based on their index.
Need to remove spaces between "< /td >" and "< td >".
Found a very useful script to prevent unwanted cells in your html table while rendering in IE9 browser.
function removeWhiteSpaces()
{
$('#myTable').html(function(i, el) {
return el.replace(/>\s*</g, '><');
});
}
This javascript function you should call when the page loads (i.e. onload event)

Programmatically add a span tag, not a Label control?

How can I add a span tag from a code behind? Is there an equivalent HtmlControl? I am currently doing it this way. I am building out rows to a table in an Itemplate implementation.
var headerCell = new TableHeaderCell { Width = Unit.Percentage(16)};
var span = new LiteralControl("<span class='nonExpense'>From<br/>Date</span>");
headerCell.Controls.Add(span);
headerRow.Cells.Add(headerCell);
I know I could use new Label(), but I am trying to avoid a server control here. Am I correct in using the LiteralControl this way? Does anyone have any better ideas of how to do this?
With HtmlGenericControl you can create a span dynamically like that :
var span = new HtmlGenericControl("span");
span.InnerHtml = "From<br/>Date";
span.Attributes["class"] = "nonExpense";
headerCell.Controls.Add(span);
Label span = new Label();
span.Text = "From<br/>Date";
span.CssClass = "nonExpense";
headerCell.Controls.Add(span);
Or, alternatively:
Label span = new Label {Text = "From<br/>Date", CssClass = "nonExpense"};
headerCell.Controls.Add(span);
new HtmlGenericControl("span")
Following the idea that our friend Canavar said.
Look under System.Web.UI.HtmlControls namespace and you will see a whole bunch of HTML controls that have been mapped to objects, if you can use those.
HtmlGenericControl fits in to any controls that are not defined in .NET and SPAN is a exemple of that.
Happy Coding.
I know I'm late but I wanted to provide my solution for this issue.
public class HtmlSpan: HtmlGenericControl
{
public HtmlSpan(): base("span") { }
}
use literalcontrol. you can add whatever html content you want.
I dont recommend label. (for more information search -label vs literal-.)

How to add a css reference within a server control?

I've built a custom server control that uses custom CSS. The problem that I have is that I have to set a reference to the css file on each page I use the control.
Can I set this reference inside the control ? So that I could just add the control and not worry about the reference.
You need to follow the below steps to add the css/javascript/image in the web control itself.
Modify the AssemblyInfo.cs file, to add the web resource
[assembly: System.Web.UI.WebResource("CustomControls.Styles.GridStyles.css", "text/css"), PerformSubstitution = true)]
Adding the required files(css/javascript/images) to the custom server control solution. Note that we can add folders in the solution and just add separate it using '.'(dot)
More importantly, we should change the BuildAction Property from Content to Embedded Resource of the newly added css/javascript/image files.
Further we should load the stored resources from the DLL. Best event for this would be OnPreRender
Below is the sample code rendering css
protected override void OnPreRender(EventArgs e)
{
bool linkIncluded = false;
foreach (Control c in Page.Header.Controls)
{
if (c.ID == "GridStyle")
{
linkIncluded = true;
}
}
if (!linkIncluded)
{
HtmlGenericControl csslink = new HtmlGenericControl("link");
csslink.ID = "GridStyle";
csslink.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl(this.GetType(), "CustomControls.Styles.GridStyles.css"));
csslink.Attributes.Add("type", "text/css");
csslink.Attributes.Add("rel", "stylesheet");
Page.Header.Controls.Add(csslink);
}
}
Similarly for Adding javascript
protected override void OnPreRender(EventArgs e)
{
string resourceName = "CustomControls.GridViewScript.js";
ClientScriptManager cs = this.Page.ClientScript;
cs.RegisterClientScriptResource(this.GetType(), resourceName);
}
Similarly using the Added Image in CSS file. Use the below code
background: url('<%=WebResource("CustomControls.Styles.Cross.png")%>') no-repeat 95% 50%;
Thanks.
Here what I use to add css reference to Page programmatically :
HtmlLink link = new HtmlLink();
link.Href = relativePath;
link.Attributes["type"] = "text/css";
link.Attributes["rel"] = "stylesheet";
Page.Header.Controls.Add(link);
Maybe you should add some code to check if the css file added to the header control.
If you want build webcontrol, that will be reusable and in one assembly with css, js and other resources, than you can use WebResources
Working with Web Resources in ASP.NET 2.0
You could do it with a ScriptManager - and this will also help you embed the stylesheet in the custom control library's DLL.
Or you could just reference the CSS from your master page. Unless you're packging a custom control library to sell etc, ScriptManager is a LOT of extra effort vs the Master Page solution
I would think you could add Canavar's code to a base class that would be included with all the classes that need it.
public class myclass : BaseClass
{
var customCSS = customcss();
Page.Header.Controls.Add(customCSS); }
and your baseclass:
public class BaseClass : Page
{
public HtnlLink customcss(){
HtmlLink link = new HtmlLink();
link.Href = relativePath;
link.Attributes["type"] = "text/css";
link.Attributes["rel"] = "stylesheet";
return link;
}
}
or you could go down the route of
myObject.Attributes.Add("style","width:10px; height:100px;");
or
myObject.Attributes.Add("style",customStyle(););
where this is in your baseclass
public String customStyle()
{
return "width:10px; height:20px;";
}
and customstyle would be a function like so:
But I would assume that you use CSS for the rest of your site, so maybe a style could just be added to your stylesheet that you use on all pages through this method you could use the below code:
myObject.Attributes.Add("class","customControl");
This will then reference the correct CSS style from your main, always included stylesheet.
Unless I am missing something here....

Categories

Resources