CssClass attribute generates class name on incorrect element - asp.net

I am working on a web forms page which has a GridView which contains two columns of radio buttons generated from an asp:RadioButton control.
I wanted to implement a "select all" checkbox in the respective column headers that would when checked select all of the corresponding radio buttons to checked in that particular column.
I wrote a small bit of jQuery which would do this but it didn't work straight away. In order for jQuery to select each radio button and mark it as checked I set the class name of the asp:RadioButton control using the CssClass attribute:
<asp:RadioButton ID="id" CssClass="myClass" runat="server" ... />
I was expecting this to generate markup something like:
<input type="radio" class="myClass" ... />
Meaning my jQuery selector would be:
jQuery("input.myClass")
Instead it has wrapped the input element in a span element and applied the class attribute I specified to the span element instead of the input element.
Is there a way to prevent ASP.NET generating this wrapping span element around my input element when using the asp:RadioButton control?
Can I get it to apply the class attribute to the actual input element, instead of the wrapping span element if ASP.NET has to generate it?
(Note: I have updated my jQuery to use a selector that works in the meantime:
jQuery("span.myClass input")
)

Web controls in the System.Web.UI.WebControls namespace may render differently in different browsers. You can't count on them rendering the same elements always. They may add anything that they think is needed to make it work in the specific browser, changing with each version of .NET.
If you want to have any control over how the controls are rendered as html, you should use the controls in the System.Web.UI.HtmlControls namespace instead. That is:
<input type="radio" id="RadioButton1" runat="server" class="myClass" />
<input type="radio" id="RadioButton2" runat="server" class="myClass" />
<input type="radio" id="RadioButton3" runat="server" class="myClass" />
They will render just as the corresponding html element, with no extra elements added. This of course means that you will have to take responsibility for the browser compatibility, as the control doesn't. Also, those controls doesn't have all the features of the controls in the WebControls namespace. So it depends on your needs for the specific situation.
You could also find another means of selecting all of the inputs in jquery, like basing it on the id (using a similar name on all of them, and a wildcard to select them all). Attribute Contains Selector

This is one of the complaints of ASP.NET WebForms is you don't get absolute control over the rendered HTML. I have used jQuery selectors exactly as you have implemented and works just fine.

You can't change the way the asp.net render it's control so you can remove the asp.net radio button and user the input tag instead with runat="server".

You can create a new ASP.Net Server Control and change inherit from WebControl to RadioButton
Then modify html after it's renderd to this. It removes the span tag and moves attributes Class And Title back from the span to the rado button input.
public class MYRADIOBUTTON: RadioButton
{
public bool AddSpanTag { get { return ViewState["AddSpanTag"] != null ? (bool)ViewState["AddSpanTag"] : false; } set { ViewState["AddSpanTag"] = value; } }
protected override void Render(HtmlTextWriter writer)
{
if (AddSpanTag)
{
base.Render(writer);
}
else
{
StringWriter w = new StringWriter();
HtmlTextWriter rbw = new HtmlTextWriter(w);
base.Render(rbw);
rbw.Close();
string html = w.GetStringBuilder().ToString();
if (html.Contains("<span"))
{
int start = html.IndexOf("<input");
int end = html.IndexOf("/>", start);
string rbHtml = html.Substring(start, (end - start));
if (CssClass != "")
rbHtml = rbHtml + " class=\"" + CssClass + "\"";
if (ToolTip != "")
rbHtml = rbHtml + " title=\"" + ToolTip + "\"";
html = rbHtml + "/>";
}
writer.Write(html);
}
}
After you build this in your webproject. Open a page in Designview then you should get a new Tab in Toolbox with your custom radiobutton control . Drag it to the page and set the Property AddSpanTag to false.
<cc1:MYRADIOBUTTON ID="btnSel" ToolTip="Select" GroupName="select" AddSpanTag="false" runat="server" />

Related

Set the style of a parent DIV to a usercontrol

I have a dynamically named DIV in a GridView which contains a user control with a dynamically assigned Parent_ID. The javascript is used to show or hide the DIV. I'll show you two examples of different rows without the ASP code.
Row 1 showing for Order # 123456:
<a href="<%#"javascript:collapseExpand('Order_Notes_Panel123456');" %>" >+</a>
<div id='Order_Notes_Panel123456' style="display:none;">
<uc:Comments_Control id="Comments_Control_ID" runat="server" Parent_ID='123456'/>
</div>
Row 2 showing for Order # 678901:
<a href="<%#"javascript:collapseExpand('Order_Notes_Panel678901');" %>" >+</a>
<div id='Order_Notes_Panel678901' style="display:none;">
<uc:Comments_Control id="Comments_Control_ID" runat="server" Parent_ID='678901'/>
</div>
The good news is that the user control binds and works perfectly. The javascript shows (sets the style to "display:block;") and hides (style set to "display:none;") the appropriate DIV each time the '+' is clicked.
Here is my problem: there is a 'Reply' link in the user control that, when clicked, does a post-back and puts the control into Edit mode. When I employ this user control on another page without a containing DIV, you won't notice a thing. However, when the 'Reply' does its post-back, the containing DIV reverts back to style="display:none;".
Can you provide a recommendation how to set the parent DIV's style to "display:block;" while a user is obviously working with it? I would imagine the appropriate code would go in the code behind of the user control when it goes into Edit mode.
Thanks,
Rob
Update: I recognize that there is no runat=server in my DIV. Since I'm trying to establish a dynamic ID for each, I get an error if I try to use the runat. That is probably the reason why I can't reach it from code behind...
I am very happy of myself... (see the YouTube video for this phrase, you'll be glad you did.)
In summary, this is what I added:
1. New Javascript function to add the name of the target DIV to a hidden field (The "collapseExpand" function is in the Site.Master. I couldn't put "load_div_to_hidden" in the Site.Master since "myhiddenField" isn't set up on every page
2. New hidden field to capture the name of the target DIV
3. New Javascript function to run on window.onload, check if we've got a post-back, and then display the value from the hidden field
4. Adding second Javascript call from the href in the link
Below are the new snippets of code:
<script type="text/javascript">
function load_div_to_hidden(obj) {
var hidden = document.getElementById('<%= myhiddenField.ClientID %>');
hidden.value = obj;
}
function windowOnLoad() {
var isPostBack = (('<%= IsPostBack %>').toLowerCase() == 'true') ? true : false;
if (isPostBack == true) {
var hid_field_value = document.getElementById('<%= myhiddenField.ClientID %>').value;
var right_div = document.getElementById(hid_field_value);
right_div.style.display = "block";
}
}
window.onload = windowOnLoad;
</script>
<input type="hidden" id="myhiddenField" runat="server" value="" />
<a href="<%#"javascript:collapseExpand('Order_Notes_Panel123456'); javascript:load_div_to_hidden('Order_Notes_Panel123456');" %>" >+</a>
<div id='Order_Notes_Panel123456' style="display:none;">
<uc:Comments_Control id="Comments_Control_ID" runat="server" Parent_ID='123456'/>
</div>
Works like a charm!

How to verify whether HTML controls exist from code behind

I have an asp.net form.
But the controls inside the form at 1 textbox and 2 dropdown lists as a row.
And there is a "plus" and "minus" buttons for users to add in and delete the rows.
When the form is submitted, I will grab the values from those controls by using Request.Form["ControlName"]
But I need to confirm whether that ["ControlName"] exists.
I can put that piece of code in try catch to confirm like this
for(int a=1;a<10;a++)
{
try
{
Response.Write(Request.Form["ControlName"+a.ToString()]);
}
catch {}
}
By doing this, the controls which don't exist will be catched by catch statement in theory.
But I am trying to use another method to do the checking like FindControl("ServerControlID")
But that one is for the server controls only.
My front code will be something like this
<input type="text" id="txt1" name="txt1"/>
<input type="text" id="txt2" name="txt2"/>
<input type="text" id="txt4" name="txt3"/>
NOTE : I cannot add in runat="server". If so, I can use FindControl()
If you want to access a control on server side (code behind), than that control must be a server control or even an html control but with runat = "server" attribute, by introducing you can access the HTML control.
<input type="text" id="txt1" name="txt1" runat = "server"/>
You could use the NameValueCollection returned by Request.Form.AllKeys.
This returns an IEnumerable
Use Linq to check it as follows:
for(int a=1;a<10;a++)
{
var paramName = "ControlName"+a.ToString();
if(Request.Form.AllKeys.Contains(paramName ))
{
Response.Write(Request.Form[paramName ]);
}
else
{
//key not present
}
}

ASP.Net User control How to read the child node

I have a user control defined like this
<%# Control .....
<Test:MyCustomControl id="xxx" runat="server>
</Test:MyCustomControl>
I would like to use this control on a page like
<Tag:MyControl runat="server">
<div>
my html
</div>
</Tag...
In my custom control codebehind I would like to read the inner html and set it to a property of Test:MyCustomcontrol
Currently I am getting an error saying that "...does not have property div"
How can I do this?
Note: For clarification the inner html can be an arbitrary html, so I need a way to read anything that user has typed in the page.
you can expose the div(running on the server) as a property from your UserControl
on the usercontrol html:
<div id="dvSomething" runat="server"></div>
on ur usercontrol codebehind ".cs file":
public System.Web.UI.HtmlControls.HtmlGenericControl TheDiv
{
get
{
return dvSomething;
}
set {
dvSomething = value;
}
}
on the page that contains the usercontrol:
WebUserControl11.TheDiv.InnerHtml = "addin something to div from page";
good luck
I will keep the other question open in case someone need a different solution:
I'm not sure about your requeriments like but here are two solutions, I hope this is what you want:
one adding control(you can add any by the way, not only textbox) and other pure html as per you described
TextBox txtAdd = new TextBox();
txtAdd.Style.Add("width", "200px");
WebUserControl11.Controls.Add(txtAdd);
TextBox txtRead = (TextBox)WebUserControl11.Controls[1];
((System.Web.UI.HtmlControls.HtmlGenericControl)WebUserControl11.Controls[0]).InnerHtml = "<b>something</b>";
string currentHtml = ((System.Web.UI.HtmlControls.HtmlGenericControl)WebUserControl11.Controls[0]).InnerHtml;
of course, the index will change depending how many elements you have on your user control

iPhone email keyboard layout with asp .net TextBox

You know how the iDevices will display a different keyboard layout depending on the HTML 5 value of the type attribute? So, <input type="email"... will display the iPad's e-mail keboard layout. I am using a .net TextBox but would like to have the iDevices show the appropriate keyboard layout for the field. But the type attribute gets overridden to "text" when the TextBox control renders. Any ideas?
No easy fix, but you can create some new control like:
public EnhancedTextBox : TextBox {
public Html5Type Html5Type { get; set; }
override AddAttributesToRender(HtmlTextWriter writer) {
// add attribute according to the selected type in the property
// something like
writer.AddAttribute("type", "email");
base.AddAttributesToRender(writer);
}
}
and use that instead of a normal TextBox
There is an update for .NET framework 4 which allows you to specify the type attribute.
http://support.microsoft.com/kb/2468871.
See feature 3 way down the page
Feature 3
New syntax lets you define a TextBox control that is HTML5 compatible. For example, the following code defines a TextBox control that is HTML5 compatible:
<asp:TextBox runat="server" type="some-HTML5-type" />
I just solved this problem with a control adapter for <asp:TextBox>. Add this class somewhere in your project and reference it from a .browser file in App_Browsers and it will let you set what ever type you want to your input control.
public class TextBoxControlAdapter : ControlAdapter
{
protected override void Render(HtmlTextWriter writer) {
var textBox = Control as WebControl;
if (textBox != null) {
var type = textBox.Attributes["type"];
if (!String.IsNullOrEmpty(type)) {
writer.AddAttribute("type", type);
}
}
base.Render(writer);
}
}
In App_Browsers\AdapterMappings.browser (for example), add this:
<adapter controlType="System.Web.UI.WebControls.TextBox" adapterType="MyProject.ControlAdapters.TextBoxControlAdapter" />
There is one more solution. Unfortunately, all of the above require extensive coding, new classes, KB installation which does not update for the iPhone os 3+.
Use this if you would like your phone to display a numeric keypad for a textbox control in ASP.NET:
pattern="[0-9]*"
<asp:textbox runat="server" id="txtNumber" pattern="[0-9]*" />
It is also possible to implement to replace with "<input runat='server' />"
However, a tidbit problem is occurred when you define <input runat='server' type='email' id='txtEmail' /> in [...].aspx file using Visual Studio 2010.
On making it with type='email', Visual Studio will remove an instance variable definition - "protected global::System.Web.UI.HtmlControls.HtmlInputText txtEmail;" in [...].aspx.designer.cs file.
So, you have to define only "<input runat='server' id='txtEmail' />" in [...].aspx.
Instead of adding type='email' attribute in [...].aspx, you can provide an attribute in code behind file as follows,
txtEmail.Attributes.Add("type", "email");

Show hide div using codebehind

I have a DropDownList for which I am trying to show a div OnSelectedIndexChanged but it says OBJECT REQUIRED.
I am binding the DataList in that div:
aspx:
<asp:DropDownList runat="server" ID="lstFilePrefix1" AutoPostBack="True"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" >
<asp:ListItem Text="Prefix1" Value="Prefix1" />
<asp:ListItem Text="Prefix2" Value="Prefix2" />
<asp:ListItem Text="Prefix3" Value="Prefix3" />
<asp:ListItem Text="Prefix1 and Prefix2" Value="Prefix1 and Prefix2" />
<asp:ListItem Text="Prefix2 and Prefix3" Value="Prefix2 and Prefix3" />
</asp:DropDownList>
<asp:DataList ID="DataList1" runat="server" RepeatColumns="4"
CssClass="datalist1" OnItemDataBound="SOMENAMEItemBound"
CellSpacing="6" onselectedindexchanged="DataList1_SelectedIndexChanged"
HorizontalAlign="Center" Width="500px">
code behind:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstFilePrefix1.SelectedItem.Text=="Prefix2")
{
int TotalRows = this.BindList(1);
this.Prepare_Pager(TotalRows);
Page.ClientScript.RegisterClientScriptBlock(GetType(), "JScript1", "ShowDiv('data');", true);
}
}
javascript:
function ShowDiv(obj)
{
var dataDiv = document.getElementById(obj);
dataDiv.style.display = "block";
}
What am I doing wrong?
You can use a standard ASP.NET Panel and then set it's visible property in your code behind.
<asp:Panel ID="Panel1" runat="server" visible="false" />
To show panel in codebehind:
Panel1.Visible = true;
Make the div
runat="server"
and do
if (lstFilePrefix1.SelectedValue=="Prefix2")
{
int TotalRows = this.BindList(1);
this.Prepare_Pager(TotalRows);
data.Style["display"] = "block";
}
Your method isn't working because the javascript is being rendered in the top of the body tag, before the div is rendered. You'd have to include code to tell the javascript to wait for the DOM to be completely ready to take on your request, which would probably be easiest to do with jQuery.
There are a few ways to handle rendering/showing controls on the page and you should take note to what happens with each method.
Rendering and Visibility
There are some instances where elements on your page don't need to be rendered for the user because of some type of logic or database value. In this case, you can prevent rendering (creating the control on the returned web page) altogether. You would want to do this if the control doesn't need to be shown later on the client side because no matter what, the user viewing the page never needs to see it.
Any controls or elements can have their visibility set from the server side. If it is a plain old html element, you just need to set the runat attribute value to server on the markup page.
<div id="myDiv" runat="server"></div>
The decision to render the div or not can now be done in the code behind class like so:
myDiv.Visible = someConditionalBool;
If set to true, it will be rendered on the page and if it's false it won't be rendered at all, not even hidden.
Client Side Hiding
Hiding an element is done on the client side only. Meaning, it's rendered but it has a display CSS style set on it which instructs your browser to not show it to the user. This is beneficial when you want to hide/show things based on user input. It's important to know that the element CAN be hidden on the server side too as long as the element/control has runat=server set just as I explained in the previous example.
Hiding in the Code Behind Class
To hide an element that you want rendered to the page but hidden is another simple single line of code:
myDiv.Style["display"] = "none";
If you have a need to remove the display style server side, it can be done by removing the display style, or setting it to a different value like inline or block (values described here).
myDiv.Style.Remove("display");
// -- or --
myDiv.Style["display"] = "inline";
Hiding on the Client Side with javascript
Using plain old javascript, you can easily hide the same element in this manner
var myDivElem = document.getElementById("myDiv");
myDivElem.style.display = "none";
// then to show again
myDivElem.style.display = "";
jQuery makes hiding elements a little simpler if you prefer to use jQuery:
var myDiv = $("#<%=myDiv.ClientID%>");
myDiv.hide();
// ... and to show
myDiv.show();
Another method (which it appears no-one has mentioned thus far), is to add an additional KeyValue pair to the element's Style array. i.e
Div.Style.Add("display", "none");
This has the added benefit of merely hiding the element, rather than preventing it from being written to the DOM to begin with - unlike the "Visible" property. i.e.
Div.Visible = false
results in the div never being written to the DOM.
Edit: This should be done in the 'code-behind', I.e. The *.aspx.cs file.
<div id="OK1" runat="server" style ="display:none" >
<asp:DropDownList ID="DropDownList2" runat="server"></asp:DropDownList>
</div>
vb.net code
Protected Sub DropDownList1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles DropDownList1.SelectedIndexChanged
If DropDownList1.SelectedIndex = 0 Then
OK1.Style.Add("display", "none")
Else
OK1.Style.Add("display", "block")
End If
End Sub
RegisteredClientScriptBlock adds the script at the top of the page on the post-back with no assurance about the order, meaning that either the call is being injected after the function declaration (your js file with the function is inlined after your call) or when the script tries to execute the div is probably not there yet 'cause the page is still rendering. A good idea is probably to simulate the two scenarios I described above on firebug and see if you get similar errors.
My guess is this would work if you append the script at the bottom of the page with RegisterStartupScript - worth a shot at least.
Anyway, as an alternative solution if you add the runat="server" attribute to the div you will be able to access it by its id in the codebehind (without reverting to js - how cool that might be), and make it disappear like this:
data.visible = false
I was having a problem where setting element.Visible = true in my code behind wasn't having any effect on the actual screen. The solution for me was to wrap the area of my page where I wanted to show the div in an ASP UpdatePanel, which is used to cause partial screen updates.
http://msdn.microsoft.com/en-us/library/bb399001.aspx
Having the element runat=server gave me access to it from the codebehind, and placing it in the UpdatePanel let it actually be updated on the screen.
Hiding on the Client Side with javascript
Using plain old javascript, you can easily hide the same element in this manner:
var myDivElem = document.getElementById("myDiv");
myDivElem.style.display = "none";
Then to show again:
myDivElem.style.display = "";
jQuery makes hiding elements a little simpler if you prefer to use jQuery:
var myDiv = $("#<%=myDiv.ClientID%>");
myDiv.hide();
... and to show:
myDiv.show();

Resources