I have a asp:Wizard control in my Web Application.I need to be able to print at any step within the wizard , and print all steps up to that step not just the current step.
I've added a print button to every step page , and tried to call the javascript:window.Print(), but only the current step gets printed.
How do i get all the steps to print in 1 page?
i'd like to try and get this working in javascript first before i go down the PDF route . I've tried doing somehting like this :
protected void Page_Load(object sender, EventArgs e)
{
StringWriter sw = new StringWriter();
HtmlTextWriter tw = new HtmlTextWriter(sw);
this.WizardStep2.RenderControl(tw);
string wizardHtmlContent = sw.ToString().Replace("\r\n", "");
string printScript = #"function printDiv(printpage)
{
var headstr = '<html><head><title></title></head><body>';
var footstr = '</body>';
var newstr = printpage;
var oldstr = document.body.innerHTML;
document.body.innerHTML = headstr+newstr+footstr;
window.print();
document.body.innerHTML = oldstr;
return false;
}";
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "PrentDiv", printScript, true);
this.Button1.Attributes.Add("onclick", "printDiv('" + wizardHtmlContent + "');");
}
and for the aspx:
<form id="form1" runat="server">
<div>
<asp:Wizard ID="Wizard1" runat="server">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
step1
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2">
step2
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
<asp:Button ID="Button1" runat="server" Text="Button" />
</div>
</form>
But i'm getting a missing runat=server error on line 3 , when i attempt to render the wizard control , so i think i may need to create a new window, then output the string before i print it , but cant seem to get that working ...Anyone any ideas ?
i have found a solution for my problem , i didnt manage to accomplish it client side , but ive managed to solve it server side which is better than going down the PDF route which i didnt want to do.
I found a great article here :
Printing in ASP.NET
which i ammended to print all steps of my wizard control in one go. thanks for all your help.
The javascript print method you're already using will work if you put the wizard steps in to a single page so they all render ...
the other way I guess is to simply browse to each step and hit your print button.
the way I would do it is use something like pdfsharp and give it the markup generates by each step and tell it to create a pdf page for each steps worth of markup ... from there the user has a pdf doc which they can simply view save or print using their usual pdf viewer.
The problem is that the javascript method is using a dom based api call to ask the browser to print the page which of course ultimately means you can only print the wizard step you're currently looking at ... using the pdf method means the user can preview the expected print out before printing and you have more control over what's printed.
It does require a bit more code though ...
pdfsharp can be found here: http://www.pdfsharp.net/Downloads.ashx
As you can see its free and open source.
Related
Output from controller below is rendered without line breaks in IE9
How to force browser to render text in separate lines as created ?
ASP.NET / Mono MVC2 is used in .NET 3.5
public ActionResult Index()
{
var sb = new StringBuilder();
sb.AppendLine("Line1");
sb.AppendLine("Line2");
return new ContentResult() { Content = sb.ToString() };
}
It depends on what you trying to do. Browser ignore simple new line, for C# it is \r\n. Use <br /> (html tag for new line) or try <pre> tag:
<pre>
Line 1
Line 2
</pre>
Demo: http://jsfiddle.net/CQeTX/
When you use AppendLine, StringBuilder appends newlines. If you want to show line breaks in the browser, you have to add <br/>:
sb.AppendLine("Line1<br/>");
sb.AppendLine("Line2<br/>");
or
sb.Append("Line1<br/>");
sb.Append("Line2<br/>");
If it is part of the html on the page
sb.AppendLine("Line1<br />");
or if it is in the code
sb.AppendLine("Line1\n");
I'm working on a website which has the following code in an ascx page:
<%Using (Html.BeginForm("MakeABooking", "User", FormMethod.Post))%>
<button type="submit" class="searchCarButton JQryStyleButton" name="btnSubmit" value="1; <%:DataBinder.Eval(c.DataItem, "currentAsset.AssetID").ToString %>; <%:DataBinder.Eval(c.DataItem, "SearchForDate").ToString %>">Make Booking</button>
<%End Using%>
This form calls the MakeABooking Function in a ViewController:
<HttpPost()> _
<ValidateInput(False)> _
Public Function MakeABooking(btnSubmit As String) As ActionResult
Dim sMan As String = btnSubmit
Dim sSegmentBooked As String = sMan.Substring(0, sMan.IndexOf(";"))
sMan = sMan.Substring(sMan.IndexOf(";") + 1)
Dim sAsseID As String = sMan.Substring(0, sMan.IndexOf(";"))
Dim sDateBook As String = sMan.Substring(sMan.IndexOf(";") + 1)
Dim BookingModel As New BookingViewModel(CInt(sAsseID), CInt(sSegmentBooked), CDate(sDateBook))
Return View("MakeABooking", BookingModel)
End Function
When using Internet Explorer 8 with Compatibility View turned on, I get the following error Length cannot be less than zero. Parameter name: length.
However, when Compatibility View is turned off, it works fine but this causes another issue on the website I'm working on where ui-selector controls are not working properly (jQuery control).
The client whom we have created this website for is using Windows XP and Internet Explorer 8, hence needing to fix problem for Internet Explorer 8, as they are not willing to use another browser like Google Chrome or Firefox in which our website works fine on.
I've managed to replicate the problem using Windows 7 IE 9 with Compatibility mode on, and the string value passed in to the MakeABooking Function i.e. btnSubmit, is "<SPAN class=ui-button-text>Make Booking</SPAN>" whereas the string passed should be something like this "1;8463;12/09/2012 12:00:00 AM", as the Function MakeABooking is looking for semi-colons, hence that error I'm getting. Does anyone know why I get the string "<SPAN class=ui-button-text>Make Booking</SPAN>" instead of what I expect as mentioned earlier?
If I can get any assistance, it will be much appreciated.
Thanks hagensoft, adding in the following extra code to the right aspx page fixed the problem.
<asp:Content ID="Meta" ContentPlaceHolderID="MetaContent" runat="server">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
</asp:Content>
I also needed to add the following line of code in the Site.Master page in the tag.
<asp:ContentPlaceHolder ID="MetaContent" runat="server" />
I want to use Thickbox in my site.
I have the following code:
<img src='#Url.Action("GetSchemaImage", "Hall", new {folderName = #Model.FolderName })'/>
This is generated markup:
<a class="thickbox" href="/Hall/GetSchemaImage?folderName=marineclub"><img src="/Hall/GetSchemaImage?folderName=marineclub"></a>
The image shows correctly, but when I click on it, it opens in the current window.
How to resolve it?
Thanks
try another signature for the HTML ActionLink helper and see if this works
#Html.ActionLink("GetSchemaImage", "Hall",new {folderName = #Model.FolderName },new{})
I'm using the object tag to render PDF in HTML, but I'm doing it in MVC like this:
<object data="/JDLCustomer/GetPDFData?projID=<%=ViewData["ProjectID"]%>&folder=<%=ViewData["Folder"] %>"
type="application/pdf" width="960" height="900">
</object>
and Controller/Action is
public void GetPDFData(string projID, Project_Thin.Folders folder)
{
Highmark.BLL.Models.Project proj = GetProject(projID);
List<File> ff = proj.GetFiles(folder, false);
if (ff != null && ff.Count > 0 && ff.Where(p => p.FileExtension == "pdf").Count() > 0)
{
ff = ff.Where(p => p.FileExtension == "pdf").ToList();
Response.ClearHeaders();
Highmark.BLL.PDF.JDLCustomerPDF pdfObj = new JDLCustomerPDF(ff, proj.SimpleDbID);
byte[] bArr = pdfObj.GetPDF(Response.OutputStream);
pdfObj = null;
Response.ContentType = "application/" + System.IO.Path.GetExtension("TakeOffPlans").Replace(".", "");
Response.AddHeader("Content-disposition", "attachment; filename=\"TakeOffPlans\"");
Response.BinaryWrite(bArr);
Response.Flush();
}
}
The problem is, as I'm downloading data first from server and then return the byte data, it is taking some time in downloading, so I want to show some kind of progress to show processing.
Please help me on this.
You may try the following (not tested under all browsers):
<div style="background: transparent url(progress.gif) no-repeat">
<object
data="<%= Url.Action("GetPDFData, new { projID = ViewData["ProjectID"], folder = ViewData["Folder"] }") %>"
type="application/pdf"
width="640"
height="480">
<param value="transparent" name="wmode"/>
</object>
</div>
Unfortunatly, there is no way (afaik) to interact with the Acrobat plugin and see when it's ready to display your PDF document.
There are components available that replace Acrobat and provide a proper Javascript interface.
I work for TallComponents on their PDFWebViewer.NET product which will display PDF without any plugins and works with ASP.NET MVC.
You do have some other options though. If you need the progress indicator because the PDF generation is taking longer than you would like you can poll the server for progress using AJAX calls.
On the server you would need to have some sort of progress information available that you can return as the result of the ajax call. In the browser you'd use the result to provide progress info to the user. There are several good examples available online (this blog for example). There are also other questions here on SO (for example here) with good pointers to more info.
If the generation process only takes a couple of seconds can you probably get way with showing a busy indicator. That could be as simple as showing a div in your page when you trigger the download from the server.
By the way, if I'm not mistaken you should replace the attachment keyword with inline in the Content-Disposition header. Setting that to attachment will cause the entire PDF to be downloaded before any content is displayed. If you set it to inline, Acrobat will start showing the first page as soon as it has downloaded enough data to do so.
Why doesn't this display the date/time when rendered?
<asp:Label runat="server" ID="test" Text="<%= DateTime.Now.ToString() %>" ></asp:Label>
Is there anyway to make this work?
Asp.net server controls don't play well with the <%=, instead you can do:
<span><%= DateTime.Now.ToString() %></span>
Ps. you could alternatively set the label's text on the code-behind. It might work for your scenario to set it on the PreRenderComplete.
I'm not sure if you've got a code behind file, but if you really need to set the label's Text property in the .aspx markup you could add the following code to the page:
<script runat="server">
protected override void OnPreLoad(EventArgs e)
{
if (!Page.IsPostBack)
{
this.test.Text = DateTime.Now.ToString();
base.OnPreLoad(e);
}
}
</script>
This way you can maintain the label control's state on postback.
Put the inline code inside the label's tag as below,
< asp:Label ID="Lbl" runat="server" Text="">
<%= DateTime.Now.ToString() %>
< /asp:Label>
Well the asp tags are rendered. You will have to set the property at runtime. or just do the <%= DateTime.Now.ToString() %>.
The simplest way to make that work would be to use a data-binding expression in place of the code render block...
<asp:Label runat="server" ID="test" Text="<%# DateTime.Now.ToString() %>" ></asp:Label>
Now the Text property will be set whenever Page.DataBind() is called, so in your code-behind you'll want something like
protected override void OnPreRender(EventArgs e)
{
if (!Page.IsPostBack)
{
DataBind();
}
base.OnPreRender(e);
}
The real problem here though is I need to set the property of a WebControl with code on the markup page. The only way I've found to do this is put the whole control in a code block. Its not elegant or suggested but when all else fails this will work.
<%
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
var htmlWriter = new HtmlTextWriter(stringWriter);
var label = new Label { Text = DateTime.Now.ToString() };
label.RenderControl(htmlWriter);
Response.Write(stringBuilder.ToString());
%>
But this won't work if you need the control to maintain state.
UPDATE:
After researching Kev's answer I did find an even better solution. I don't have a code behind (its an MVC page) but you can still reference a control on the page through a code block so my new solution is the following. Note - You have to place the code block first for this to work.
<%
lblTest.Text = DateTime.Now.ToString();
%>
<asp:label runat="server" ID="lblTest" />
Thanks for the inspiration Kev!