In trying to make my ASP.Net 4.0 site validate to HTML5 the best I can with the current specification. I have a DataList that always adds cellspacing="0" I've tried different ways of removing the cellspacing="0". I have added a CSS style sheet which does flow over.
Anyone know how to make the DataList conform to the HTML 5 validation?
Actual Code:
Validation Error Message: The cellspacing attribute on the table element is obsolete. Use CSS instead.
Generated Code:
I am not a big fan of DataList - many time, the markup generates is table based and hence semantically incorrect. So I will suggest to use some alternate control such as Repeater or ListView if possible.
Now, if you are in situation where you have plenty of data lists... one of the solution would be to have your own custom DataList control to explicitly override cellspacing attribute such as
public class MyDataList : DataList
{
protected override Style CreateControlStyle()
{
var s = new TableStyle();
s.CellSpacing = -1;
return s;
}
}
You can then probably use ASP.NET Tag Mapping to substitute built-in data-list with your implementation across all pages from config.
Related
Background: We run dozens of sites for clients; all use an identical code base (ASP.NET WebForms) but completely different designs. Page structure is generated programmatically from SQL Server meta-data, using controls such as Panel, which are added to the ASP.NET page's Controls collection, and become DIVs in the rendered HTML.
Objective: We want to migrate eventually to ASP.NET CORE. However, there seems to be no equivalent to the page's controls collection. The closest thing I can find is the RenderTreeBuilder to add a Blazor component.
Question: Is it possible use BuildRenderTree to add a component which contains our home-baked HTML (for instance, to contain everything between <body> and </body>?
I've read articles such as:
https://chrissainty.com/building-components-via-rendertreebuilder/
https://learn.microsoft.com/en-us/aspnet/core/blazor/components?view=aspnetcore-3.1#manual-rendertreebuilder-logic
... and experimented with adding HTML elements, but it's extremely cumbersome, and I'd like to programmatically generate the HTML for pretty much the whole page, and add it as one RenderFragment (is that the right term?).
Is this possible? Is there an alternative?
Edit:
#Henk's answer, using the MarkupString struct, and mine, using RenderTreeBuilder.AddMarkupContent seem similar in terms of effort and plumbing required.
Are there any pros and cons of the two approaches I should consider?
If you just want HTML (plain, dead) then you don't need a rendertree:
<h1>My Page</h1>
#MyHtmlComposer()
#code{
private MarkupString MyHtmlComposer()
{
string html = "<p>Hello</p>";
return new MarkupString(html);
}
}
I hadn't come across the MarkupString struct, so #Henk's answer is really helpful. I've now also come across the RenderTreeBuilder.AddMarkupContent method, so I'll offer this as an alternate answer:
My markup:
#page "/"
<PageBuilder></PageBuilder>
PageBuilder is a class that inherits from ComponentBase:
public class PageBuilder : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder b)
{
base.BuildRenderTree(b);
b.OpenElement(0, "div");
b.AddMarkupContent(1, TheContent());
b.CloseElement();
}
public string TheContent()
{
return "<div>This is the generated content</div>";
}
I'll edit my original question a little, as I'd like to know whether there's anything to choose between this approach and #Henk's.
You can also render a string as HTML like this:
#page "/test";
<h1>My Page</h1>
#((MarkupString)content)
#code{
//Get content from Database
string content = "<p>Hello</p>";
}
See section "Raw HTML" here
As my title says, I have a set property crash problem.
Here's the scenario:
I have created a simple custom ASP.Net server control that generates some text.
I wanted to give design-time property for that text so its style can be accessed by developers from the properties window.
All the properties in the properties window are working except the ones with the type System.Web.UI.WebControls.Style that I have created.
Here is my property:
[Bindable(true)]
[Category("Appearance")]
[Description("The style for the header")]
[Localizable(true)]
public Style HeaderTextStyle
{
get
{
Style s = (Style)(ViewState["HeaderTextStyle"] == null ? Styles.defaultHeaderStyle : ViewState["HeaderTextStyle"]);
return s;
}
set
{
ViewState["HeaderTextStyle"] = value;
}
}
Oh and Styles.defaultHeaderStyle is just a property from an internal class that returns a new Style.
Let me point that the hanging/crashing occurs only when I CHANGE the property, so it cannot be from the getter.
I won't paste my render control because the error occurs even when I'm not rendering anything.
What is it that causes this?
Thank you.
I found the answer to my problem.
You see, the Style class is a property that has sub-properties and it is called a complex property. Complex properties ( a property that has subproperties) need custom state management to use view state. The Style class need design-time attributes to enable persistence within the control's tags. So what I wrote in my original post will not work.
For complete explanation visit: Server Control Properties Example from MSDN
I managed to implement it using that example. I hope this will be useful to others out there.
I have a .NET question. For my particular application which is catoring to mobile devices (specifically blackberry at the moment), I am using validators (required field validator to be exact).
The problem is that I have disabled javascript from asp.net (by specifying ClientTarget="ie4", but setting EnableClientScript="False" on the validator tags has the same effect). The actual issue is that when the validator is invisible, it emits "nbsp;" instead of nothing, is there some way to override this unwanted result?
Please do not reply solutions that include css or javascript, as I am unable to use either in my particular situation.
Thank you.
Display=Static means that a single nonbreaking space (" ") is emitted. This last behavior exists so that table cells containing only validators do not collapse to nothing when valid.
From here.
As Frédéric Hamidi said, you could try Display=Dynamic instead, but if you're insistent on using Display=Static, I think your only option is to extend the validator and override the Render method.
protected override void Render(HtmlTextWriter writer)
{
if (this.Display == ValidatorDisplay.Static && this.IsValid)
{
writer.Write(String.Empty);
}
else
{
base.Render(writer);
}
}
Static validators will indeed render an entity when hidden.
Try using dynamic validators instead, by setting their Display property to ValidatorDisplay.Dynamic.
I'd like to force the consumer of a control to give a property a value when placing the control on a page.
In VisualStudio when you create an < img > tag without attributes SRC or ALT on a user control, it gets underlined saying that SRC and ALT are required attributes. I assume this is just a special handling of the tag by the editor, but is there a way to define a similar behavior for controls?
If the control had a property defined like this:
public object AProperty
{
get
{
if (ViewState["AProperty"] == null)
{
throw new Exception("AProperty is a required property of this control");
}
return ViewState["AProperty"];
}
set { ViewState["AProperty"] = value; }
}
Is there a way to use a Custom Attribute or something else that would flag in the designer?
You could use the Microsoft.Build.Framework.Required attribute. This would require a value to be set at build time or the build will fail with a message which indicates that the property does not have a value.
I don't believe there is an attribute to indicate that a specific tag must be included in a server control (or at least I don't see any such attribute on the System.Web.UI.HtmlControl.Image class). I believe that the litle underlines are part of the HTML validation of the IDE.
You could always create a custom attribute which throws a warning if a property is missing
While Microsoft.Build.Framework.Required is probably the best answer here, for others who stumble upon this and can't use .NET 4.0, you can also use this method:
http://forums.asp.net/t/1238319.aspx
Is there an accepted way to "move" a control.
My client wants to place a certain chunk of markup (representing some visual element) in one of several different places on the page. The locations are different to the point that I can't effect the change on CSS along (by floating it or something).
I considered just putting the control in multiple spots with Visible set to "false," then displaying the one in the place they wanted for that particular page.
However, the code for this control is not trivial -- there's a couple template sections, for instance. Having to dupe this in multiple places would get unwieldy. Also, I don't want to have to work with this control strictly from the code-behind for the same reason.
So, I'd like to put it in one place on the Web form, the move it around based on where I want it. Could I put Placeholders in different spots, have the control in one spot, then remove and add it to the right spot? I suspect this would work.
Does someone have a better idea? Is there a best practice for this?
I'd recommend using a placeholder control, moving your markup into a separate user control, then loading this at runtime and adding it to the relevant placeholder.
Eg.
// Load a user control
MyControl userCtrl = (MyControl) LoadControl("~/Controls/MyControl.ascx");
// Or create an instance of your control
SubclassedControl subclassedCtrl = new SubclassedControl();
// Do stuff with controls here
userCtrl.LoadData();
subclassedCtrl.Text = "Hello World";
// Check which placeholder to add controls to
PlaceHolder placeHolder = (foo=="bar") ? placeHolder1 : placeHolder2;
// Add the controls
placeHolder.Controls.Add(userCtrl);
placeHolder.Controls.Add(subclassedCtrl);
This will avoid cluttering up your page with unnecessary markup, and loading it at runtime will also avoid unnecessary confusion later, when another developer looks at the code and can't immediately see why a control is in one place in the markup, but renders on a completely different part of the page.
An alternative (and one I've seen done many times before) is through javascript and the DOM. Render your control inside a hidden div tag. So you would render your content here:
<div id='rendercontent' style='display:none'>
.. control here ..
</div>
Then, lets say you wanted to move it all here (the span tag is inside because that's what we're going to replace):
<div id='newlocation1'><span></span></div>
You would define the following javascript:
<script language="JavaScript">
function replaceNode(newElementID, targetElementID)
{
var targetElement=document.getElementById(targetElementID);
var newElement=document.getElementById(newElementID);
targetElement.replaceChild(newElement, targetElement.firstChild);
}
</script>
And when you want to move the content to the new location, call:
<script language="JavaScript">
replaceNode('rendercontent','newlocation1');
</script>
Do Web Parts do what you want to do?
Or, you can change the parent programmatically of your controls to move them into a separate area.
You can override the Render method and place the controls wherever you want in the html.
You only need to add controls to the Controls collection that must interact on the server. The rest of your HTML can just be written to the response stream. If you override Render you can create the html anyway you see fit, placing the controls in any order.
Below is an example of how to write out your html.
protected override void Render(HtmlTextWriter writer)
{
AddAttributesToRender(writer);
writer.RenderBeginTag(TagKey);
writer.RenderBeginTag(HtmlTextWriterTag.Div);
_control.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
}
You could always put panels in the pre-defined locations and add the control to the specific panel at runtime.. Here's an example adding a label (the label could be replaced with any control).
Dim lblDisplay As Label = New Label()
lblDisplay.ID = "myLabel"
lblDisplay.Text = "Some Text"
pnlDisplay.Controls.Add(lblDisplay)
As far as...
"Also, I don't want to have to work
with this control strictly from the
code-behind for the same reason."
I think you're going to have to do most of your work in the code behind.
PS.. a good example of the whole usercontrol setup can be downloaded here..
http://www.asp.net/downloads/starter-kits/time-tracker/