Dynamically Changing HTML - c#

I am trying to create a HTML page where the "body" color changes depending on some data being gathered from the RAM. If the RAM fills up beyond a certain threshold then I want the color to change.
<body style="background-color:<%=
if(MemoryPercentage < 33)
{
//set to green.
}
else if(MemoryPercentage < 66)
{
//set to yellow.
}
else
{
//set to red.
}%>">
Thank you for your help,
Aaron

<body
style="background-color:<%= MemoryPercentage < 33? "green":
(MemoryPercentage < 66? "yellow":"red") %>;">

I'd prefer using CSS classes and separating the logic out so it is more readable.
<style type="text/css">
.warn {
background-color: #00ffff;
}
.error {
background-color: #ff0000;
}
.ok {
background-color: #00ff00;
}
</style>
<%
var klass = MemoryPercentage < 33 : "ok" ? (MemoryPercentage < 66 ? "warn" : "error");
%>
<body class="<%= klass %>">

While you can definitely apply the style directly using the sytle attribute of the body tag (as suggested in this answer), general best practices revolving around HTML discourage this.
What you should do is place these styles in a stylesheet which is referenced on your page, and then have different names for the classes.
Then, in your code, apply the class that has the style you want depending on your logic to the class attribute of the body element.

Just an aside to the other answers:
<body id="Body" runat="server"> will make the tag accessible to Page_Load() & friends as an HtmlGenericControl, so you can handle the logic and set Body.CssClass without the template-y markup. Makes it a little less messy / easier to maintain.

Related

Converting HTML to PDF Invoice

I'm trying to generate HTML page ( C# Razor View ) that will be converted to PDF ( using wkhtmltopdf )and printed on pre-printed stationery.
My problems is, that the pre-printed stationery has a header ( easy )
and tear-off part at the bottom (4cm) which should be blank until the very last page where some additional information is printed.
The whole invoice is being generated as
<table><thead></thead><tbody></tbody></table>
So how can I set margin of X on every page except the last printed
and on that last printed page instead of margin actually print something?
Tried to use with last-child selector but that did not work.
Perhaps some other solution will be more suitable for this using .Net Core ( some linux apps can be used as well )?
You can use the CSS #page rule to specify the page margins. You can also use this to specify additional margins for left & right-hand pages (to account for binding) and for the first page but not, it would seem, for the last page!
/* Default left & right is 2cm, top & bottom margin is 4cm */
#page { margin: 4cm 2cm }
/* First page, 10 cm margin on top */
#page :first {
margin-top: 10cm;
}
/* Left pages, a wider margin on the left */
#page :left {
margin-left: 3cm;
margin-right: 2cm;
}
/* Right pages, a wider margin on the right */
#page :right {
margin-left: 2cm;
margin-right: 3cm;
}
Further reading: https://www.w3.org/TR/CSS21/page.html#page-box
Finally I got to the bottom of that.
As the top of the page should not be a problem ( can be handled the same way as well , but the table thead is another option )
My solution is:
wkhtmltopdf test.html --footer-html footer.html output.pdf
And the whole trick is withing the footer.html file:
<!DOCTYPE html>
<html>
<head>
<script>
var mainHeader = "test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>";
var secondHeader = "OOOOOOOOOOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPPOPO<br>";
function selectHeader() {
var vars = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) {
var z = x[i].split('=', 2);
vars[z[0]] = decodeURIComponent(z[1]);
}
if (vars["page"] == vars['topage']) {
document.getElementById('main').innerHTML = secondHeader;
} else {
document.getElementById('main').innerHTML = mainHeader;
}
if (vars["page"] == vars['frompage']) {
document.getElementById('test').innerHTML = secondHeader;
}
}
</script>
</head>
<body onload="selectHeader()">
<div style="min-height: 6cm; background-color: aqua; max-height: 6cm; overflow:visible;">
<div id="main" onload="selectHeader()">
</div>
</div>
</body>
</html>
ps.
Read somewhere that without !DOCTYPE html it might not work.
Thanks for all the help

How to stop gridview creating a div in asp.net

I've got the following asp.net code that generates a listitem dynamically and populates it with a panel that contains a gridview:
Panel panBlocks = new Panel();
panBlocks.ID = "PanBlockQuestionID" + recordcount.ToString();
panBlocks.Width = 1300;
panBlocks.Height = 100;
panBlocks.BackColor = System.Drawing.ColorTranslator.FromHtml("#fabb3d");
GridView gvEmployee = new GridView();
gvEmployee.ID = "gvEmployees" + recordcount.ToString();
gvEmployee.AutoGenerateColumns = true;
gvEmployee.DataSource = dtBlocks;
gvEmployee.DataBind();
gvEmployee.Style.Add("position", "relative");
panBlocks.Controls.Add(gvEmployee);
It generates the gridview but wraps it in a div. How do I stop it generating the div as it messes up the styling. The html it generates is:
<li id="CPH_Body_liQuestions3" class="liQuestions" style="height:40px;" myCustomIDAtribute="3"><a></a><input type="image" name="ctl00$CPH_Body$lblImg3" id="CPH_Body_lblImg3" class="liQuestionsLabel2" src="../../Images/gtk_cancel.png" style="width:30px;" /><input type="image" name="ctl00$CPH_Body$lblImg3" id="CPH_Body_lblImg3" class="liQuestionsLabel2" src="../../Images/phone_book_edit.png" style="width:30px;" /><span id="CPH_Body_lblID3" class="liQuestionsLabel" style="display:inline-block;width:35px;">298,</span><span id="CPH_Body_lblQuestionType3" class="liQuestionsLabel" style="display:inline-block;width:25px;">1, </span><span id="CPH_Body_lblMsgPrompt3" class="liQuestionsLabel" style="display:inline-block;width:300px;">Fit nylon spacer BG502 to tray,</span><span id="CPH_Body_lblExpectedResp3" class="liQuestionsLabel" style="display:inline-block;width:100px;">YES,</span><span id="CPH_Body_lblImg3" class="liQuestionsLabel" style="display:inline-block;width:30px;"> img: </span><span id="CPH_Body_lblFailMsg3" class="liQuestionsLabel" style="display:inline-block;width:300px;">Not fitted,</span><span id="CPH_Body_lblRetryMsg3" class="liQuestionsLabel" style="display:inline-block;width:300px;">Retry,</span><span id="CPH_Body_lblStart3" class="liQuestionsLabel" style="display:inline-block;width:10px;">,</span><span id="CPH_Body_lblEnd3" class="liQuestionsLabel" style="display:inline-block;width:10px;">,</span><img id="CPH_Body_lblImg3" class="liQuestionsLabel2" onclick="showPanel('CPH_Body_liQuestions3')" src="../../Images/block3.png" style="width:30px;" /><div id="CPH_Body_PanBlockQuestionID3" style="background-color:#FABB3D;height:100px;width:1300px;">
<div>
<table cellspacing="0" rules="all" border="1" id="gvEmployees3" style="border-collapse:collapse;position:relative;">
<tr>
<th scope="col">B1ID</th><th scope="col">B1IncEx</th><th scope="col">B1Criteria</th>
</tr><tr>
<td>3</td><td>EX</td><td>590P</td>
</tr>
</table>
</div>
</div></li>
How do I stop the div being generates please as I can't apply styling to it.
Many Thanks
Use a PlaceHolder instead of a Panel, the difference is that the PlaceHolder is not rendered as a div whereas a Panel always.
The PlaceHolder control does not produce any visible output and is used only as a container for other controls on the Web page.
While I haven't found a way to remove the DIV completely, it is possible to change it so that the DIV no longer wraps the TABLE if you're in a position where you can define and use your own custom GridView control.
The trick is to prematurely close the opening DIV tag, so the TABLE follows it in the HTML, rather than being inside it. If needed, you can also add attributes to the DIV, such as a class name, to ensure that it does not affect the surrounding HTML.
using System.Web.UI;
public class MyGridView
: System.Web.UI.WebControls.GridView
{
public MyGridView()
{
}
public override void RenderControl(HtmlTextWriter writer)
{
/* The underlying GridView class renders a DIV as a container in
RenderControl(), so we can add attributes here, such as a class
to hide it.
*/
writer.AddAttribute(HtmlTextWriterAttribute.Class, "hidden");
base.RenderControl(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
/* We don't want the underlying GridView's container DIV to actually
wrap the internal TABLE, so calling RenderEndTag() here will cause
it to be closed before the TABLE is rendered (which happens in
RenderChildren())...
*/
writer.RenderEndTag();
base.RenderContents(writer);
/* ...However, when this function exits, RenderControl() will call
RenderEndTag() itself to close what is expected to be the container
DIV, so we need to provide a open tag for it. We'll use a SPAN as
that will have the least effect on the HTML and we could, of
course, add any required attributes to style it, etc, if required.
*/
writer.RenderBeginTag(HtmlTextWriterTag.Span);
}
/* If you need to add any additional attributes to the TABLE tag, you
can do that here with a call to writer.AddAttribute(); if not, this
override is redundant.
protected override void RenderChildren(HtmlTextWriter writer)
{
// TODO: call writer.AddAttribute() if required
base.RenderChildren(writer);
}
*/
}
HACK ALERT!
Clearly, this is implementation-specific and subject to change with new versions of ASP.NET. However, in most cases, an upgrade to the ASP.NET version would most likely require testing/review anyway, so it shouldn't be too much of an issue.

Scrolling Dynamic DIV

I have a DIV which has images and hyperlinks, which are added in C# by CODE
mStr.Append(" <div id='wn'>");
mStr.Append("<div id='lyr1'> <ul id='horiz'>");
if (dv.Count > 0) {
for (int i = 0; i < dv.Count; i++) {
mStr.Append("<li width='450' height='110' style='padding-left:5px; padding-right:5px; padding-top:2px; padding-bottom:2px;'>");
mStr.Append("<a href='PlayGame.aspx?GameID=" + GameLib.Utilities.Encrypt(dv[i][1].ToString()) + "'>");
mStr.Append("<img src='../" + dv[i][10].ToString() + "' width='156px' height='109px' style='padding-left:0px;' />");
mStr.Append("</a>");
mStr.Append("</li>");
}
mStr.Append("</ul></div></div>");
RelatedGames.InnerHtml.Remove(0, RelatedGames.InnerHtml.Length);
RelatedGames.InnerHtml = mStr.ToString();
}
..but the problem is that I want to scroll the DIV so that i can go through all images. I tried many ways in JQuery but it has been stuck and static. I will be grateful for any suggestions.
Or, is there any other way that the same functionality can be achieved?
Simply add the following CSS:
#lyr1 {
overflow: auto;
}
Overflow is a CSS property that specifies how content that is larger than its parents should be displayed. The default value is visible, which means that everything will be displayed, even if it goes beyond the size of its parent (which it does, in your case). Setting it to auto will make everything that doesn't fit in the parent hidden, and will add scrollbars whenever necessary. To make scrollbars always visible, do overflow: scroll;.
Live demo: http://jsfiddle.net/DanVicBez/kNk4y/
Just use a css property overflow:scroll to the target div
<div id='lyr1' style='overflow:scroll'>

How do you style WebView control in Windows Store App?

I have C# / XAML win store app which receives various data from json. one piece of it - html string.
I display that string using WebView.NavigateToString
However I don't see how can I style it. Normally I would use blend to get default style and then edit it. But Blend doesn't let me style WebView.
I ended up wrapping the json html into
<body style='background-color:black;color:white' />
but this approach doesn't let me use theming which the rest of the application does.
What is the 'proper' way to style and / or format content of the WebView?
Another solution is making a WebViewContentHelper (or so) class. You may pass the theme and style the CSS according to that. For example:
string content = WebViewContentHelper.WrapHtml(originalHtmlString, backGroundColor, webView.ActualHeight);
webView.NavigateToString(content);
You can adapt this class that already copies the Font styling from Windows 8 and gives you horizontal scrolling, also arranges content in columns, just as ItemDetails Template:
class WebContentHelper
{
public static string HtmlHeader(double viewportWidth, double height) //adapt parametres
{
var head = new StringBuilder();
head.Append("<head>");
head.Append("<meta name=\"viewport\" content=\"initial-scale=1, maximum-scale=1, user-scalable=0\"/>");
head.Append("<script type=\"text/javascript\">"+
"document.documentElement.style.msScrollTranslation = 'vertical-to-horizontal';"+
"</script>"); //horizontal scrolling
//head.Append("<meta name=\"viewport\" content=\"width=720px\">");
head.Append("<style>");
head.Append("html { -ms-text-size-adjust:150%;}");
head.Append(string.Format("h2{{font-size: 48px}} "+
"body {{background:white;color:black;font-family:'Segoe UI';font-size:18px;margin:0;padding:0;display: block;"+
"height: 100%;"+
"overflow-x: scroll;"+
"position: relative;"+
"width: 100%;"+
"z-index: 0;}}"+
"article{{column-fill: auto;column-gap: 80px;column-width: 500px; column-height:100%; height:630px;"+
"}}"+
"img,p.object,iframe {{ max-width:100%; height:auto }}"));
head.Append(string.Format("a {{color:blue}}"));
head.Append("</style>");
// head.Append(NotifyScript);
head.Append("</head>");
return head.ToString();
}
public static string WrapHtml(string htmlSubString, double viewportWidth, double height)
{
var html = new StringBuilder();
html.Append("<html>");
html.Append(HtmlHeader(viewportWidth,height));
html.Append("<body><article class=\"content\">");
html.Append(htmlSubString);
html.Append("</article></body>");
html.Append("</html>");
return html.ToString();
}
}
You cannot style/extend webview apparently, Webview is not a derivative of control subclass (it does not have a control template) and is rather hosted in its own HWND. You are probably better off using webviewbrush. See this sample
You can style like this
public static string Scape(string htmlContent, string fontColor)
{
var htm = "<html> <head> <script type=\"text/javascript\"></script> <style> body { color: "+ fontColor +"; } </style> </head> <body>" + htmlContent +"</body></html>";
return htm;
}

Self closing Html Generic Control?

I am writing a bit of code to add a link tag to the head tag in the code behind... i.e.
HtmlGenericControl css = new HtmlGenericControl("link");
css.Attributes["rel"] = "Stylesheet";
css.Attributes["type"] = "text/css";
css.Attributes["href"] = String.Format("/Assets/CSS/{0}", cssFile);
to try and achieve something like...
<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css" />
I am using the HtmlGenericControl to achieve this... the issue I am having is that the control ultimatly gets rendered as...
<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css"></link>
I cant seem to find what I am missing to not render the additional </link>, I assumed it should be a property on the object.
Am I missing something or is this just not possible with this control?
I think you'd have to derive from HtmlGenericControl, and override the Render method.
You'll then be able to write out the "/>" yourself (or you can use HtmlTextWriter's SelfClosingTagEnd constant).
Edit: Here's an example (in VB)
While trying to write a workaround for umbraco.library:RegisterStyleSheetFile(string key, string url) I ended up with the same question as the OP and found the following.
According to the specs, the link tag is a void element. It cannot have any content, but can be self closing. The W3C validator did not validate <link></link> as correct html5.
Apparently
HtmlGenericControl css = new HtmlGenericControl("link");
is rendered by default as <link></link>. Using the specific control for the link tag solved my problem:
HtmlLink css = new HtmlLink();
It produces the mark-up <link/> which was validated as correct xhtml and html5.
In addition to link, System.Web.UI.HtmlControls contains classes for other void element controls, such as img, input and meta.
Alternatively you can use Page.ParseControl(string), which gives you a control with the same contents as the string you pass.
I'm actually doing this exact same thing in my current project. Of course it requires a reference to the current page, (the handler), but that shouldn't pose any problems.
The only caveat in this method, as I see it, is that you don't get any "OO"-approach for creating your control (eg. control.Attributes.Add("href", theValue") etc.)
I just created a solution for this, based on Ragaraths comments in another forum:
http://forums.asp.net/p/1537143/3737667.aspx
Override the HtmlGenericControl with this
protected override void Render(HtmlTextWriter writer)
{
if (this.Controls.Count > 0)
base.Render(writer); // render in normal way
else
{
writer.Write(HtmlTextWriter.TagLeftChar + this.TagName); // render opening tag
Attributes.Render(writer); // Add the attributes.
writer.Write(HtmlTextWriter.SelfClosingTagEnd); // render closing tag
}
writer.Write(Environment.NewLine); // make it one per line
}
The slightly hacky way.
Put the control inside a PlaceHolder element.
In the code behind hijack the render method of the PlaceHolder.
Render the PlaceHolders content exactly as you wish.
This is page / control specific and does not require any overrides. So it has minimal impact on the rest of your system.
<asp:PlaceHolder ID="myPlaceHolder" runat="server">
<hr id="someElement" runat="server" />
</asp:PlaceHolder>
protected void Page_Init(object sender, EventArgs e)
{
myPlaceHolder.SetRenderMethodDelegate(ClosingRenderMethod);
}
protected void ClosingRenderMethod(HtmlTextWriter output, Control container)
{
var voidTags = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { "br", "hr", "link", "img" };
foreach (Control child in container.Controls)
{
var generic = child as HtmlGenericControl;
if (generic != null && voidTags.Contains(generic.TagName))
{
output.WriteBeginTag(generic.TagName);
output.WriteAttribute("id", generic.ClientID);
generic.Attributes.Render(output);
output.Write(HtmlTextWriter.SelfClosingTagEnd);
}
else
{
child.RenderControl(output);
}
}
}

Categories