to print my Gridview i used following event Button_Print_Click. below is my code:
private void Button_Print_Click(object sender, EventArgs e)
{
GridView1.PagerSettings.Visible = false;
GridView1.DataSource = DataLoad();
GridView1.DataBind();
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
GridView1.RenderControl(hw);
string gridHTML = sw.ToString().Replace("\"", "'").Replace(System.Environment.NewLine, "");
StringBuilder sb = new StringBuilder();
sb.Append("<script type = 'text/javascript'>");
sb.Append("window.onload = new function(){");
sb.Append("var printWin = window.open('', '', 'left=0");
sb.Append(",top=0,width=1000,height=600,status=0');");
sb.Append("printWin.document.write(\"");
sb.Append(gridHTML);
sb.Append("\");");
sb.Append("printWin.document.close();");
sb.Append("printWin.focus();");
sb.Append("printWin.print();");
sb.Append("printWin.close();};");
sb.Append("</script>");
ClientScript.RegisterStartupScript(this.GetType(), "GridPrint", sb.ToString());
GridView1.DataSource = DataLoad();
GridView1.DataBind();
}
But by focusing the page, it doesn't show the css properties. For example my GridViewHeader text font looks simple but not bold!! is there anything wrong with the code? Why dont I get the original CSS styled page printed?
Please help thank you.
The problem is that you are calling a pop-up using window.open(), this popup opens a new HTML page, and even if you inject javascript generated HMTL in it, it doesn't have any reference to your CSS file.
Try to add a link to it in the string output
sb.Append("printWin.document.write(\"");
sb.Append("<link rel='stylesheet' type='text/css' href='...your.css'>")
sb.Append(gridHTML);
Note that this is really an odd way to print a html page, I would find it more simple to generate a extra Print CSS for this using the #media rules, and call the javascript print() on the very same page : see eg http://edutechwiki.unige.ch/en/CSS_for_print_tutorial
Related
I'm working on a console application that's supposed to spit out an html document that contains a table and maybe some javascript.
I thought about writing the html by hand:
streamWriter.WriteLine("<html>");
streamWriter.WriteLine("<body>");
streamWriter.WriteLine(GetHtmlTable());
streamWriter.WriteLine("</body>");
streamWriter.WriteLine("</html>");
... but was wondering if there is a more elegant way to do it. Something along these lines:
Page page = new Page();
GridView gridView = new GridView();
gridView.DataSource = GetDataTable();
gridView.DataBind();
page.Controls.Add(gridView);
page.RenderControl(htmlWriter);
htmlWriter.Flush();
Assuming that I'm on the right track, what's the proper way to build the rest of the html document (ie: html, head, title, body elements) using the System.Web.UI.Page class? Do I need to use literal controls?
It would be a good idea for you to use a templating system to decouple your presentation and business logic.
Take a look at Razor Generator which allows the use of CSHTML templates within non ASP.NET applications.
http://razorgenerator.codeplex.com/
I do a lot of automated HTML page generation. I like to create an HTML page template with custom tags where to insert the dynamic controls, data, or literals. I then read template file into a string and replace the custom tag with the generated HTML like you are doing above and write the HTML file back out of the string. This saves me the time of creating all the tedious support HTML for the design template, css, and supporting JS.
Template File Example
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<CUSTOMHEAD />
</head>
<body>
<CUSTOMDATAGRID />
</body>
</html>
Create HTML From Template File loaded into string Example
private void GenerateHTML(string TemplateFile, string OutputFileName)
{
string strTemplate = TemplateFile;
string strHTMLPage = "";
string strCurrentTag = "";
int intStartIndex = 0;
int intEndIndex = 0;
while (strTemplate.IndexOf("<CUSTOM", intEndIndex) > -1)
{
intStartIndex = strTemplate.IndexOf("<CUSTOM", intEndIndex);
strHTMLPage += strTemplate.Substring(intEndIndex,
intStartIndex - intEndIndex);
strCurrentTag = strTemplate.Substring(intStartIndex,
strTemplate.IndexOf("/>", intStartIndex) + 6 - intStartIndex);
strCurrentTag = strCurrentTag.ToUpper();
switch (strCurrentTag)
{
case "<CUSTOMHEAD />":
strHTMLPage += GenerateHeadJavascript();
break;
case "<CUSTOMDATAGRID />":
StringWriter sw = new StringWriter();
GridView.RenderControl(new HtmlTextWriter(sw));
strHTMLPage += sw.ToString();
sw.Close();
break;
case "<CUSTOMANYOTHERTAGSYOUMAKE />":
//strHTMLPage += YourControlsRenderedAsString();
break;
}
intEndIndex = strTemplate.IndexOf("/>", intStartIndex) + 2;
}
strHTMLPage += strTemplate.Substring(intEndIndex);
try
{
StreamWriter swHTMLPage = new System.IO.StreamWriter(
OutputFileName, false, Encoding.UTF8);
swHTMLPage.Write(strHTMLPage);
swHTMLPage.Close();
}
catch (Exception ex)
{
// AppendLog("Write File Failed: " + OutputFileName + " - " + ex.Message);
}
}
Im building out a c# web app here and I have a Listview. I would like to have a button on the page that when clicked it will print the listview easily. Anyone have any idea how this would be done?
Thanks
Try Adding the following code inside the button click event. Hope fully it will help.
this.ListView1.DataBind();
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
ListView1.RenderControl(hw);
string ListViewHTML = sw.ToString().Replace("\"", "'").Replace(System.Environment.NewLine, "");
StringBuilder sb = new StringBuilder();
sb.Append("<script type = 'text/javascript'>");
sb.Append("window.onload = new function(){");
sb.Append("var printList = window.open('', '', 'left=0");
sb.Append(",top=0,width=800,height=700,status=0');");
sb.Append("printList.document.write(\"");
sb.Append(ListViewHTML);
sb.Append("\");");
sb.Append("printList.document.close();");
sb.Append("printList.focus();");
sb.Append("printList.print();");
sb.Append("printList.close();};");
sb.Append("</script>");
ClientScript.RegisterStartupScript(this.GetType(), "ListViewPrint", sb.ToString());
this.ListView1.DataBind();
There are 2 options that I can think of:
Send this to a different page with an ID (perhaps the order number?) in the query string; read the order id from the query string, and output the details in the page. Then call window.print on window.load
Something like:
Order o = DAL.GetOrderByID(int.Parse(Request.QueryString["OrderID"]));
//output the order in this new page...
On this new page, have a line like this:
window.onload=function(){window.print();};
Use this jquery plugin to do it. It creates a frame in the page and calls .print on the frame. Seems very simple to implement.
I have a behindcode javascript. it is to show a javascript dialog box.
however, it keep show this error
The name 'ClientScript' does not exist in the current context
This code was put inside masterpage. I had also use the exactly same code at other aspx file, and it work out fine apart from this..
here is my code:
protected void Button2_Click(object sender, EventArgs e)
{
string message = "Order Placed Successfully.";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<script type = 'text/javascript'>");
sb.Append("window.onload=function(){");
sb.Append("alert('");
sb.Append(message);
sb.Append("')};");
sb.Append("</script>");
ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", sb.ToString()); string script = "alert('abc');";
}
Try:
Page.ClientScript
instead to see if it makes a difference.
For cs file the sample is;
ClientScript.RegisterClientScriptBlock(this.GetType(), "{some text for type}", "alert('{Text come to here}'); ", true);
for masterpage cs the sample is;
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "{some text for type}", "alert('{Text come to here}'); ", true);
On the master page try ScriptManager.RegisterStartupScript() instead. Watch out, the signature slightly differs from Page.ClientScript.RegisterClientScriptBlock().
Documentation of the ScriptManager Class
I have a button and onclick is set to this method which should display a simple JS alert pop up window:
string message = "File is already open. <br>Please close the file and try again.";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<script type = 'text/javascript'>");
sb.Append("window.onload=function(){");
sb.Append("alert('");
sb.Append(message);
sb.Append("')};");
sb.Append("</script>");
ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", sb.ToString());
I have used the code above before and it has worked but not this time.
The only difference is that I was using master pages for the other site and not for this one, and this one also has a timer going.
Is there anything JS related to load in the <head> of the aspx page?
protected void btnToCSV_Click(object sender, EventArgs e)
{
try
{
StreamWriter writer = new StreamWriter(#"\\server location\test.csv");
Some writer.write stuff...
writer.Close();
}
catch (Exception ex)
{
lblMessage.Visible = true;
string message = "File is already open. Please close the file and try again.";
ClientScript.RegisterClientScriptBlock(
this.GetType(),
"alert",
string.Format("alert('{0}');", message),
true);
}
}
Try with this simplyfied version
string message = "File is already open. <br>Please close the file and try again.";
ScriptManager.RegisterClientScriptBlock(
UpdatePanel1, // replace UpdatePanel1 by your UpdatePanel id
UpdatePanel1.GetType(), // replace UpdatePanel1 by your UpdatePanel id
"alert",
string.Format("alert('{0}');",message),
true );
You are not encoding anything here:
sb.Append(message);
If the message is Hello Jean d'Arc (notice the single quote) you will end up with the following code:
alert('Hello Jean d'Arc');
I am leaving you imagine the result of this => a javascript error of course.
To fix this error make sure that you have properly encoded the argument. One way to do this is to JSON serialize it:
var serializer = new JavaScriptSerializer();
sb.AppendFormat("alert({0});", serializer.Serialize(message));
Also since you have already includeed the <script> tags, make sure that you pass false as last argument of the RegisterClientScriptBlock function to avoid adding them twice:
ClientScript.RegisterClientScriptBlock(
this.GetType(),
"alert",
sb.ToString(),
false // <!---- HERE
);
And here's how the full code might look like:
var message = "File is already open. <br>Please close the file and try again.";
var sb = new StringBuilder();
sb.Append("<script type=\"text/javascript\">");
sb.Append("window.onload=function() {");
var serializer = new JavaScriptSerializer();
sb.AppendFormat("alert({0});", serializer.Serialize(message));
sb.Append("};");
sb.Append("</script>");
ClientScript.RegisterClientScriptBlock(
this.GetType(),
"alert",
sb.ToString(),
false
);
Another remark is that if you are doing this in an AJAX call you should use the ClientScript.RegisterStartupScript method.
I want to use string replace to replace the tag {tag:shoppingcart} and in that it would load the user control:
<%# Register TagPrefix="basket" TagName="cart" src="~/controls/basket.ascx" %>
<basket:cart id="test" runat="server"></basket:cart>
I would be defining the controls at the top of the page that needs them.
My question is what is my best way to achieve the following if it is at all possible
string templatehtml;
templatehtml = template[0].Cms;
string newhtml;
newhtml = templatehtml.Replace("{tag_pagecontent}", currentPage[0].Body);
newhtml = templatehtml.Replace("{tag_shoppingcart}", <basket:cart id="test" runat="server"></basket:cart>);
litcontent.Text = newhtml;
It's the <basket:cart code i am having trouble with.
We actually do a very similar thing, except we have placeholder divs on the page.
In the page_init method, we get a reference to the placeholder div, load the user control into the page, and then add the usercontrol to the div's controls.
For example (very rough code):
// Get a reference to the div
Control oUserControlDiv = this.FindControl("divUserControl");
// Load the user control
Control oControl = this.LoadControl("controls/basket.ascx");
oControl.EnableViewState = true;
// Clear the existing control(s) from the div
oUserControlDiv.Controls.Clear();
// And add the new one
oUserControlDiv.Controls.Add(oControl);
Please try this instead:
var basket = new Basket();
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (HtmlTextWriter writer = new HtmlTextWriter(sw))
{
basket.RenderControl(writer);
}
string basketHtml = sb.ToString();
newhtml = templatehtml.Replace("{tag_shoppingcart}", basketHtml);