ASP.NET custom control, can I taking data from a <template> and convert it to a string? - asp.net

I'm trying to have an asp.net custom control with a field like:
<ErrorTemplate>
<h1>Error</h1>
<p>Blue wizard shot the food</p>
</ErrorTemplate>
What I want to end up with is:
<h1>Error</h1><p>Blue wizard shot the food</p> in a string in my codebehind.
At the moment, the process I use to get this data out of the template is:
First this gets instantiated into a placeholder by my code:
ErrorTemplate.InstantiateIn(errorPHolder);
which is an asp.net placeholder control - it has to be instantiated into something which can support controls.
What I then want to do is add this to my page using JQuery and a variable, like this:
string script = "var Errortemplate = " + errorPHolder.ToString() + ";";
scriptmanager.register(script); // pseudocode
so the result would be, on my page:
var Errortemplate = '<h1>Error</h1><p>Blue wizard shot the food</p>';
Then I can use JQuery to do someDiv.html(Errortemplate);
Finally resulting in whatever they put in <ErrorTemplate> appearing on the page
Because I'm using JQuery it might be possible to do this a different way, such as adding the placeholder to the page into a hidden div and using JQuery to copy the values out.
Any ideas?

Have you tried to render your control?
StringBuilder sb = new StringBuilder();
using (StringWriter tw = new StringWriter(sb))
{
using (HtmlTextWriter hw = new HtmlTextWriter(tw))
{
errorPHolder.RenderControl(hw);
}
}
// its HTML string representation of errorPHolder
string html = sb.ToString();

Related

ASP.NET Custom web control styles Render style rules

I have a custom web control that inherits from ASP.NET button control. In Render method override, I rendering my own HTML output (div). The question is how I can render style attributes for that control in most correct way.
I can simply iterate over the Style collection in for / foreach loop and write it to HTMLTextWriter, but maybe .NET has a build in method that writes the style definition to htmlwriter ?
Thanks
It sounds like what you want is the ApplyStyle() method:
var style = new Style();
style.ForeColor = System.Drawing.Color.Red;
style.BackColor = System.Drawing.Color.Yellow;
var ctrl = new WebControl();
ctrl.ApplyStyle(style);
The solution is to use the Value property of CssStyleCollection object in ASP.NET WebControl.
http://msdn.microsoft.com/en-us/library/system.web.ui.cssstylecollection.value.aspx

using JavaScript, find the ClientID of .NET control nested deep within a master page

The short question:
*takes deep breath*
How I can ClientID of TableRow inside Table added to PlaceHolder, which is in a UserControl inside a Web Part added to a SharePoint page using a MasterPage?
The explanation:
I'm building a usercontrol that dynamically shows SPList items, one per Web.UI.Table(). The 2nd row of the Table() will be hidden at first, with an image used to initiate some JavaScript to hide/show the row at the clients browser (rather than use postback or ajax - I have reasons).
The Table() is then added to a PlaceHolder in a UserControl, which is then used by a WebPart, and that WebPart is added to a SharePoint Page, which of course uses a MasterPage. I'm having real trouble working out the JavaScript method to find the ClientID of the TableRow, given that it's nested so deeply.
My .ascx code looks something like this..
<script type="text/javascript">
function showHidden(itemId) {
var controlId = document.getElementById('<%= phDownloadTable.ClientID %>');
//alert(controlId);
document.getElementById(controlId).style.display = (document.getElementById(controlId).style.display == "table-row") ? "none" : "table-row";
}
</script>
<asp:PlaceHolder ID="phTable" runat="server"></asp:PlaceHolder>
and my .cs codebehind is something like this..
Table myTable = new Table();
TableRow hiddenRow = new TableRow();
hiddenRow.ID = "row" + itemId;
hiddenRow.Attributes.Add("style","display: none;");
... create TableCells and add to hiddenRow...
TableRow displayRow = new TableRow();
TableCell toggleCell = new TableCell();
Image toggleImage = new Image();
toggleImage.ImageUrl = "/images/myimage";
toggleImage.Attributes.Add("onclick","javascript:showHidden('" + hiddenRow.ClientID + "');
toggleCell.Controls.Add(toggleImage);
displayRow.Cells.Add(toggleCell);
... create more TableCells and add to displayRow
myTable.Rows.Add(displayRow);
myTable.Rows.Add(hiddenRow);
the result is that the toggleImage "onclick" attribute shows showHidden('row999');, which passes 'row999' to the JavaScript function, but I cannot figure out there how to get the full clientId of the TableRow it refers to.
The source of my page shows the clientId to be ctl00_SPWebPartManager1_g_eda9b9e9_4c7a_48e0_a2aa_fd8cdd65de6c_ctl00_row999, which is longer than I'm used to seeing, and seems to contain two 'ct100_' parts, suggesting multiple levels of controls.
Any ideas would be greatly appreciated. I've tried all the usual avenues (googleing for 'javascript .net control client id' and the like, but so far I've not found anything that helps. Most suggest document.getElementById('<%= myControl.ClientId %>')... which is fine, but I don't know 'myControl' - I need that send from the toggle image.
Fingers crossed!!
Kevin
If you cant set the client id, you should be able to set a class, and that should be respected by .nat.
Them you can select the element by class name.
JavaScript has no wildcard selection options. Try using jQuery, that makes things more flexible.
Then you can use something like:
$("tr[id*='<%= phDownloadTable.ClientID %>']").css("display", your value);
this way you will still find the right element, even when it's moved to another place on the page.
Here is a more detailed explanation on how to use these wildcard selectors:
http://api.jquery.com/attribute-contains-selector/
With plain JavaScript you can do a document.getElementsByTagName('tr') and then loop those to find the right object.
If you are using Framework 4.0 you can set the ClientIdMode of the page like this:
Page.ClientIDMode = System.Web.UI.ClientIDMode.Static;
That way you can have more predictable client ids. For example, you can have id's without all the ctl00_ prefixes.

ASP.NET how to display data without GridView

I am newbie in ASP.NET.
I have prepared an arraylist of Product and want to display in the page.
Easiest way is binding the arraylist to GridView.
But I don't have flexibility there, since it will automatically generate a TABLE behind the scene.
Is there any other way to give us flexibility to really control the HTML output, for e.g i want to display using UL tag instead of TABLE tag.
var products = new ArrayList();
products.Add("product1");
products.Add("product2");
products.Add("product3");
var builder = new StringBuilder();
foreach (var product in products)
{
builder.Append("<li>" + product + "</li>");
}
Response.Write("<ul>" + builder.ToString() + "</ul>");
You can prefer using Repeater Control instead. With Repeater's templates, you can easily inject your html output to your output.
Here there's an exapmle of using Repeater. Actually example also try to add a table but, the topic is to show you how to use templates.
Use
Response.Write("<ul><li>item1</li><li>item1</li><li>item1</li><li>item1</li></ul>")
You get all the control u need with that

Getting JS Error (for - event.srcElement.id) in WebForm

I am building a dynamic user control (ascx) which contains a placeholder. Inside the placeholder, there will be n tables. Inside each table, in one of the cells i have the link button as below.
HyperLink lnkButton = new HyperLink();
lnkButton.ID = "lnkButton_" + ID.ToString();
lnkButton.Text = tstText;
lnkButton.NavigateUrl = "javascript:JS_Click();";
I have to call a JS function on the link button click (no postback).
In the JS function, i have to get the id of the control that invoked that JS function. In this case, it will be link button. I am writing the below code in the JS Function:
var ctrl = event.srcElement.id;
but i am getting 'Object Required' error in javaScript.
Few other things: This user control will be loaded in default.aspx page and the JS Function i am writing in default.aspx.
I am not sure why this is not working. I am using IE6/7, VS 2005. Is there any other function or way available to get the srcElement.id. Please help.
Try passing this along when you invoke the method
lnkButton.NavigateUrl = "javascript:JS_Click(this);";
then you can write this in your JS_Click event
function JS_Click(obj)
{
alert("Now I have my object " + obj.id);
}
Another option would be to use jQuery and wire up to the click event on your link buttons.
Add a CssClass attribute to the LinkButton's you are creating:
HyperLink lnkButton = new HyperLink();
lnkButton.ID = "lnkButton_" + ID.ToString();
lnkButton.Text = tstText;
lnkButton.CssClass = "linkButton";
Then write the follwoing JS/ JQuery in your ASPX page:
$(document).ready(function()
{
$('.linkButton', '#userControlID').click(function(e)
{
alert('You clicked linkbutton with ID ' + e.target.id);
});
});
In the above example each link button has class="linkButton" and they are contained within your usercontrol with ID="userControlID".

Overriding Render on Sharepoint page

I have overriden Sharepoint page's Render method to cut out some script tag from the html sent to client browser like this:
protected override void Render(HtmlTextWriter originalWriter)
{
string content = string.Empty;
using (StringWriter stringWriter = new StringWriter())
{
using (HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter))
{
//render the page to my temp writer
base.Render(htmlWriter);
htmlWriter.Close();
//get page content that would normally be sent to client
content = stringWriter.ToString();
stringWriter.Close();
}
}
//replace the script tag
Regex regex = new Regex(#"<script>.*RTE_ConvertTextAreaToRichEdit.*<"+"/script>");
content = regex.Replace(content, string.Empty);
//write modified html to the original writer
originalWriter.Write(content);
}
After this change something strange happened: a part of page that usually is in the upper-right corner and says "Welcome XXX" is not displayed properly. When I view the source of the page, this text is writter BEFORE HTML tag - before any html starts. I can't figure out what is going on for last two days.
Have you got any ideas, has anyone had similar problem?
Have you checked your Regex? Regex are greedy. This means that by default it returns the longest match possible.
So if your HTML looks something like this:
<html>
...
<!-- first script element -->
<script>...RTE_ConvertTextAreaToRichEdit...</script>
<!-- first script element ends -->
<!-- second script element -->
<script>...</script>
<!-- second script element ends -->
...
</html>
The Regex matches all the stuff between the start of the first script element and the end of the second script element. After the replace your output should be:
<html>
...
<!-- first script element -->
<!-- second script element ends -->
...
</html>
You can turn your Regex in an ungreedy or lazy one (find smallest possible match). Add a ? after the * and that should do it:
Regex regex = new Regex(#"<script>.*?RTE_ConvertTextAreaToRichEdit.*?</script>");
This might solve the problem. Look here for more info.
You may have some luck using the HTML agility pack. HTML Parsers are better at... parsing... html than regexs are.
http://www.codeplex.com/htmlagilitypack
HTMLAgilityPack is full of bugs, don't use it! If you need simple solution, you can write your own method. Otherwise you it will be much better to use https://github.com/google/gumbo-parser, it has .Net wrapper called gumbo.bindings
This is a sharePoint issue actually... happens in 2010 and 2013 as well.
if you manipulate the Render the way you have in your sample it is going to gank.
You cant write back to the writer directly. use:
StrinBuilder sb = new StringBuilder();
StringWriter str = new StringWriter(sb);
HtmlTextWriter wrt = new HtmlTextWriter(str);
base.Render(wrt);
wrt.close();
string html = sb.ToString();
html = SomeFunctionManipulatingYourHTML(html).Trim();
if (html.Length >0)
{
Response.Buffer = true;
Response.Clear();
Response.ContentType = "text/html";
Response.Write(html);
Response.Flush();
Response.End();
}
Worked for me... You will still have to populate the top right corner "Welcome Message" as that is populated after Render but at least you can now manipulate it and have clean HTML. I just populated that part of the page using RegEx after the fact.

Resources