I am using the HTMLAgility pack to update the source of an existing ASP page with new elements by loading the ASP Page into an HTMLDocument, searching for a node and then using the 'InsertAfter' method to insert a new HTMLNode after this node. However, the text I use to create the new node is always being converted to lower case. e.g. If I insert a node with the text
<asp:HiddenField EnableViewState="false" ID="LOGON" runat="server" />
it gets converted to
<asp:hiddenfield enableviewstate="false" id="LOGON" runat="server"></asp:hiddenfield>
The code I have at the moment is of the form
var HTMLToInsert = "<asp:HiddenField EnableViewState="false" ID="LOGON" runat="server" />"
var NewNode = HtmlNode.CreateNode(HTMLToInsert);
Form.InsertAfter(NewNode, _PreviousNode);
I don't want this conversion. I have added the OptionOutputOriginalCase = true option to the HTMLDocument but this does not seem to affect new nodes added to the document, only existing nodes.
Is there any way of stopping the HTMLAgility pack converting my text to lower case.
Related
From your help I have managed to get a very nice PDF generation tool built. It builds a PDF based off of a 5 page template. On the 3rd and 5th page there is a possibility of needing additional pages added and moving the next pages down. The 5th page is landscape even. Everything works perfect except one little additional functionality that I am looking for.
The template that I have built has form fields on the fifth page. Therefore, I use the following code to fill the field:
var pdfReader = new PdfReader(existingFileStream);
var stamper = new PdfStamper(pdfReader, newFileStream);
var form = stamper.AcroFields;
form.SetField("fkClientName", clientName);
The field gets filled just fine, but not on the additional pages. Which is weird because I do call this line:
PdfImportedPage templatePage = stamper.GetImportedPage(pdfReader, 5);
I feel like it should see that there is form fields on that fifth page. However, I read that stamper.GetImportedPage does not retrieve form fields. I don't really care if it's a form field or text. I just need the client name at the top of each generated additional page. Here is what my columntext code looks like that builds the additional pages:
while (true)
{
ct.SetSimpleColumn(-75, 75, PageSize.A4.Height + 25, PageSize.A4.Width - 200);
if (!ColumnText.HasMoreText(ct.Go()))
break;
pageNum++;
stamper.InsertPage(pageNum, new Rectangle(792f, 612f));
stamper.GetOverContent(pageNum).AddTemplate(templatePage, 0, -1f, 1f, 0, 0, PageSize.A4.Width);
ct.Canvas = stamper.GetOverContent(pageNum);
}
If you had company stationery with some kind of background and you wanted to create a document that has flowing text (a column that can flow over to the next page) that also has a repeating header, then I would prefer using PdfWriter.
I'd use PdfWriter to add the content (without using ColumnText, just use the page size and the margins to define the column) and I would add the background and the header using page events. See for instance the Stationery example from my book.
I'd create a subclass for PdfPageEventHelper and I'd load the page you want to see repeated into a PdfImportedPage instance named page:
PdfReader reader = new PdfReader(STATIONERY);
page = writer.getImportedPage(reader, 1);
You may also want to initialize a Phrase with the name of your customer:
header = new Phrase(customerName);
Then you override the onEndPage() method like this:
public void onEndPage(PdfWriter writer, Document document) {
writer.getDirectContentUnder().addTemplate(page, 0, 0);
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, header, 36, 806, 0);
}
Now you don't have to worry about ColumnText and new pages. Every time a new page is created, the background and the header will be added automatically.
However, you are using PdfStamper because your original document isn't company stationery: it's a 5 page document. If this document doesn't contain any interactive elements (you've created it using iTextSharp, so you know if it's a flat document or not), I'd still try the PdfWriter approach and change the page instance in the event whenever a new page is needed.
If you want to keep on using PdfStamper, you'll have to add the header in a different way. For instance using a different ColumnText instance, or, if it's a single line, using ColumnText.showTextAligned(). If you don't know the coordinates for the header, you can retrieve the position of the field using the getFieldPositions() method.
Usually to sort columns in a RadGrid I use the sortexpression and text in GridTemplateColumn. But now its different; here I have a RadGrid with several columns, All of them are GridTemplateColumns. I have a collection binding the RadGrid.
<telerik:GridTemplateColumn ItemStyle-BorderWidth="0" ItemStyle-HorizontalAlign="Left"
HeaderStyle-Font-Bold="true" UniqueName="CustomerSupplierName" ShowSortIcon="true">
<ItemTemplate>
<asp:Label ID="lblSupplierName" runat="server" />
<%-- Text='<%# Eval("SupplierNameText")%>'/>--%>
</ItemTemplate>
</telerik:GridTemplateColumn>
This is one of those columns. Now in the databound function I populate the grid. I have a radiobutton list on my page completely away from this grid. Based on its selected index I change the value to be populated into this specific column (UniqueName="CustomerSupplierName"). Like this
In ItemDataBound:
If rblCustomersSuppliers.SelectedIndex = 0 Then
Dim lblSupplierName As Label = e.Item.FindControl("lblSupplierName")
lblSupplierName.Text = cont.SupplierNameText
Else
Dim lblSupplierName As Label = e.Item.FindControl("lblSupplierName")
lblSupplierName.Text = cont.CustomerOrganization
End If
So I either bind a suppliername or customerorganization based on selection. Now I need this column to be sortable. How do i do that? If you need more info, please ask. Thanks
EDIT:
Itemdatabound
If TypeOf e.Item Is GridHeaderItem Then
If rblCustomersSuppliers.SelectedIndex = 0 Then
rgContractHistory.MasterTableView.GetColumn("CustomerName").Visible = False
rgContractHistory.MasterTableView.GetColumn("SupplierName").Visible = True
Else
item("CustomerName").Text = "Customer"
rgContractHistory.MasterTableView.GetColumn("CustomerName").Visible = True
rgContractHistory.MasterTableView.GetColumn("SupplierName").Visible = False
End If
End If
Firstly, the UniqueName attribute should not used in sorting as it is intended to be a unique identifier of the column; instead the DataField should define the column (from the database) to sort by.
So the event handlers you want to consider looking at is the DataBinding or, if using Advanced Data Binding, the NeedDataSource. From here it might be possible to change the DataField assigned to the column.
Example code for getting the column:
Dim columnToChange As GridTemplateColumn = CType(grdUsers.MasterTableView.Columns.FindByUniqueNameSafe("CustomerSupplierName"), GridTemplateColumn)
If rblCustomersSuppliers.SelectedIndex = 0 Then
columnToChange.DataField = "SupplierNameText"
Else
columnToChange.DataField = "CustomerOrganization"
End If
An alternative method would be to have two separate columns, hiding and showing them depending on the currently selected RadioButton, this would require a reasonable amount of code changing as you would need to clear the filter text of the column being hidden, and probably move it into the column being shown. (Sorry but I believe it would be quite involved and I don't really have time to go into an example)
None of the above code has been tested/syntax checked but hopefully will give you reasonable pointers as to where to look next.
I am trying to alternate a CSS class in a <fieldset>. Normally a #helper function would work fine (see the #helper below), however I have two (2) circumstances that won't allow it to work properly.
First, I am using a Input.Edit.cshtml field template in ~/Views/EditorTemplates/Fields.
This basically means that as I build up a form, the Input.Edit.cshtml file is being called each time for as many <input>'s as I have in my form.
Second, I am using a condition to check the path of the URL in order to only apply this CSS alternating class on pages below a certain path. Specifically, I want to apply this change to pages under my ~/Services path. On all other pages I do not want the change applied. I check this condition using Request.Url.AbsoluteUri as you see below.
This is where I think my problem lies, as the alternating code is applied but then because it is called again for the same condition on the same page it is applied incorrectly due to my logic.
Now it could be that I am just stuck with the problem.
Here is the code:
#{
string CurrentUrl = Request.Url.AbsoluteUri;
}
#helper ResponsiveCss(string cssClass)
{
if (ViewBag.count == null) { ViewBag.count = 0; }
<text>class="#(ViewBag.count % 2 == 1 ? cssClass : "one-half last")"</text>
ViewBag.count++;
}
#if (CurrentUrl.Contains("Services"))
{
<fieldset #ResponsiveCss("one-half")>
//Label and Input code
</fieldset>
}
What should happen is that the class="one-half" is applied on the first <fieldset> that is created in the form, and then class="one-half last" on the second that is created.
Instead what is happening is that class="one-half" is NOT being applied on the first <fieldset> that is created, but rather ALL <fieldset>'s are being created with class="one-half last".
Sorry if that is not clear. Any thoughts on if I can make this work given the circumstances (and how)? Thanks.
Hopefully this solves your problem.
Alternating style
Instead of alternating the class name, you can use the nth-of-type or nth-child pseudo-classes.
fieldset:nth-of-type(odd) {}
fieldset:nth-of-type(even) {}
See this example: http://jsfiddle.net/cx9UG/
Note: These pseudo-classes can also be used in JQuery selector and document selector (querySelector and querySelectorAll)
CSS depending on URL
This is really CSS depending on the view. Just create two CSS bundles then apply in to the appropriate views.
View with alternating style #Styles.Render("~/Content/alternating")
View without alternating style #Styles.Render("~/Content/mono")
The EditorTemplate should not need to know the URL.
I've set up a basic ReportView as follows:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" Font-Size="8pt" ProcessingMode="Remote" WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt">
<ServerReport ReportPath="/Reports/TestReport" ReportServerUrl="http://test/ReportServer" />
</rsweb:ReportViewer>
Now to adjust the height/width of the ReportView I can do something simple such as:
Height = "500px" Width = "300%"
I even found something super handy that dynamically resizes the ReportViewer based on the size of the report itself:
AsyncRendering = "false" SizeToReportContent = "true"
Doing the above will get rid of any pesky scrollbars around the ReportViewer, as it will just grow large enough to fit around the entire report. In terms of height this is fine, however I need the width of the report to always stay at a specified value (to make things look less messy).
Is this possible? Can I somehow set Width to 900px for example, and then use SizeToReportContent or the equivalent so the ReportViewer's height automatically adjusts itself to the size of the report itself without it affecting the 900px width I set.
Thanks for any help!
There's two ways of doing this,
Via C# on PageLoad:
private void Page_Load(object sender, System.EventArgs e)
{
// Set Report's Current Page & Width.
ReportViewer.CurrentPage = Report.CurrentPage;
ReportViewer.Width = new Unit(Report.Width);
// Where Report.Width is the format "12in"
// I think it accepts pixels as well. I'm not positive though.
}
Via Javascript
function AdjustWidths() {
// This grabs the first div containing "1_" since the ReportViewer Div is "1_" + ReportViewerName.
// ReportViewerName being the Identifier in the C# PageLoad. (In the example above: "ReportViewer").
var ReportViewerID = $($("div[id*=1_]")[0]).attr("id");
// Sets the width equal to the inner "_fixedTable" which is the contents.
$("#" + ReportViewerID).css("width", $("#" + ReportViewerID + "_fixedTable").css("width"));
}
The javascript method isn't full-proof (however, I have not had any problems so far). It's just a JQuery script I created to adjust the size of the viewer to be a full page. So adjust the width as desired. This will not get you what you want but with some minor changes it'll get you there.
Hope this was helpful.
I have a telerik RadGrid that gets populated with data from a SQL database when the grid loads. The first column lists a name, which needs to be a hyperlink to another part of the website. I have tried a couple different options, neither of which gets me the results I need.
The first way I tried was using a GridHyperLinkColumn. However that does not allow me to change the displayed text of the hyperlink programmatically when the grid gets populated with data.
<telerik:GridHyperLinkColumn DataNavigateUrlFields="joblink" DataNavigateUrlFormatString="/Job.aspx?id={0}" Text="JobName">
taskDR.Item("joblink") = dataReader("publicID")
taskDR.Item("joblink").Text = dataReader("name") 'This is what I would like to do
The other option was to use a GridBoundColumn and bind a Hyperlink to it.
<telerik:GridBoundColumn DataField="joblink" UniqueName="joblink">
Dim jobhyperlink As New HyperLink()
jobhyperlink.Text = dataReader("name")
jobhyperlink.NavigateUrl = "/Job.aspx?id=" & dataReader("publicID").ToString()
taskDR.Item("joblink") = jobhyperlink
However instead of displaying the hyperlink in the joblink column, all that displays is "System.Web.UI.WebControls.HyperLink"
I looked into the DataTextField and DataTextFormatString properties of GridHyperLinkColumn, but I couldn't find a way to alter those fields programmatically.
you can try a template column and just place a html tag and use Eval function to bind the things the way you want.
Check out this demo - http://demos.telerik.com/aspnet-ajax/grid/examples/generalfeatures/columntypes/defaultcs.aspx
I finally figured it out.
<telerik:GridHyperLinkColumn UniqueName="joblink" Text="jobname" DataNavigateUrlFields="joblink" DataNavigateUrlFormatString="/Employer/Job.aspx?action=edit&id={0}" DataTextField="jobname" DataTextFormatString="{0}">
Dim taskDT As New DataTable
taskDT.Columns.Add("jID")
taskDT.Columns.Add("jobname") 'You need one column for the DataTextField
taskDT.Columns.Add("joblink") 'and another for the DataNavigateUrlField
While dataReader.Read()
Dim taskDR = taskDT.NewRow()
taskDR.Item("jobname") = dataReader("name")
taskDR.Item("joblink") = dataReader("publicID")