iPhone email keyboard layout with asp .net TextBox - asp.net

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");

Related

Client-side validation for two separate conditions

Is there a way to validate asp.net text box for input using built-in validators for two distinct conditions? The text box is used in conjunction with a date picker and presently I have RegularExpressionValidator like this to validate:
<asp:TextBox ID="tbStartDate" runat="server" Width="100" CssClass="TextCompact">yyyy</asp:TextBox>
<asp:HyperLink ID="hlStartDate" runat="server" ImageUrl="~/Images/iconCalendar.gif"></asp:HyperLink><br />
<asp:RegularExpressionValidator ID="revStartDate" ControlToValidate="tbStartDate"
CssClass="TextCompact" runat="server" ErrorMessage="* Invalid Date" ValidationExpression="^(\d{4})$" />
which fires everytime an invalid date is entered - you can use the date picker or you can type in a date string.
So the issue is that I only want to validate if there is data in the text box. If the text box is empty I want it to pass through without validation.
Is this possible or would a custom client side validation be required?
Thanks,
Risho.
Update:
I've decided to write my own validator class derived from the BaseValidator class and wired it up but I get a compiler error.
namespace Abcdefg1234
{
public class Custom_Validator : BaseValidator
{
public Custom_Validator()
{
}
protected override bool EvaluateIsValid()
{
String value = this.GetControlValidationValue(this.ControlToValidate);
return ValidateControls(value.Trim());
}
public static bool ValidateControls(string value)
{
if(Regex.IsMatch(value, #"^(\d{4})$") == true)
return true;
else if(value == "")
return true;
else
return false;
}
}
}
Then I included the page directive tag:
<%# Register TagPrefix="Cv" Namespace="Abcdefg1234" TagName="CustomValidaitonX" %>
and the actual tag:
Cv:Custom_Validator ID="cvtbStartDate" ControlToValidate="tbStartDate" runat="server" ErrorMessage="* Invalid Date" />
I get a unknown server tag. Any ideas? Thanks.
The only built-in validator that fires on an empty text box would be the RequiredFieldValidator. If a textbox is empty, the other validators associated with it won't fire on form submission.
In other words, you should be fine just as you are, with the RegularExpressionValidator not firing if you submit with the textbox still empty. Are you experiencing different behavior?
ETA: You need to specify the Assembly name in your Register page directive for the Custom_Validator to be recognized. I don't believe the tag name is required for a custom control.

Access dynamically generated control from code behind

I load a piece of html which contains something like:
<em> < input type="text" value="Untitled" name="ViewTitle" id="ViewTitle" runat="server"> </em>
into my control. The html is user defined, do please do not ask me to add them statically on the aspx page.
On my page, I have a placeholder and I can use
LiteralControl target = new LiteralControl ();
// html string contains user-defined controls
target.text = htmlstring
to render it property. My problem is, since its a html piece, even if i know the input box's id, i cannot access it using FindControl("ViewTitle") (it will just return null) because its rendered as a text into a Literal control and all the input controls were not added to the container's control collections. I definitely can use Request.Form["ViewTitle"] to access its value, but how can I set its value?
Jupaol's method is the prefer way of adding dynamic control to a page.
If you want to insert string, you can use ParseControl.
However, it doesn't cause compilation for some controls such as PlaceHolder.
Your process is wrong, you are rendering a control to the client with the attribute: runat="server"
This attribute only works if the control was processed by the server, you are just rendering as is
Since your goal is to add a TextBox (correct me if I'm wrong), then why don't you just add a new TextBox to the form's controls collection???
Something like this:
protected void Page_Init(object sender, EventArgs e)
{
var textbox = new TextBox { ID="myTextBoxID", Text="Some initial value" };
this.myPlaceHolder.Controls.Add(textbox);
}
And to retrieve it:
var myDynamicTextBox = this.FindControl("myTextBoxID") as TextBox;
I have created several working examples and they are online on my GitHub site, feel free to browse the code

CssClass attribute generates class name on incorrect element

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" />

How can I include additional markup within a 'Content' inner property of an ASP.Net WebControl?

I've searched the site and I cannot find a solution for my problem, so apologies if it's already been answered (I'm sure someone must have asked this before).
I have written a jQuery Popup window that I've packaged up as a WebControl and IScriptControl. The last step is to be able to write the markup within the tags of my control. I've used the InnerProperty attribute a few times, but only for including lists of strongly typed classes.
Here's my property on the WebControl:
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public something??? Content
{
get
{
if (_content == null)
{
_content = new something???();
}
return _content;
}
}
private something??? _content;
Here's the HTML Markup of what I'm after:
<ctr:WebPopup runat="server" ID="win_Test" Hidden="false" Width="100px" Height="100px"
Modal="true" WindowCaption="Test Window" CssClass="window">
<Content>
<div style="display:none;">
<asp:Button runat="server" ID="Button1" OnClick="Button1_Click" />
</div>
<%--Etc--%>
<%--Etc--%>
</Content>
</ctr:WebPopup>
Unfortunately I don't know what type my Content property should be. I basically need to replicate the UpdatePanel's ContentTemplate.
EDIT: So the following allows a Template container to be automatically created, but no controls show up, what's wrong with what I'm doing?
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ITemplate Content
{
get
{
return _content;
}
set
{
_content = value;
}
}
private ITemplate _content;
EDIT2: Overriding the CreateChildControls allows the controls within the ITemplate to be rendered:
protected override void CreateChildControls()
{
if (this.Content != null)
{
this.Controls.Clear();
this.Content.InstantiateIn(this);
}
base.CreateChildControls();
}
Unfortunately I cannot now access the controls within the ITemplate from the codebehind file on the file. I.e. if I put a button within my mark as so:
<ctr:WebPopup runat="server" ID="win_StatusFilter">
<Content>
<asp:Button runat="server" ID="btn_Test" Text="Cannot access this from code behind?" />
</Content>
</ctr:WebPopup>
I then cannot access btn_Test from the code behind:
protected void Page_Load(object sender, EventArgs e)
{
btn_Test.Text = "btn_Test is not present in Intellisense and
is not accessible to the page. It does, however, render correctly.";
}
EDIT3: FIXED! Edit 2 is the correct soluion. It was just Visual Studios 2010 being a pain in the buttocks. Closed the app and reopened it and all my controls within the Content property were accessible on the page.
EDIT4: Edit 2 didn't fix the issue. I had already tried the [TemplateInstance(TemplateInstance.Single)] attribute before anyone had mentioned it, however at the time I didn't think it had made a difference. It appears Visual Studios 2010 is just being weird today.
Since I removed the tag and it carried on working, I assumed the attribute hadn't made a difference. Since going back to the code AGAIN the controls have become unavailable. Adding the attribute back in allowed it all to work and for the controls to be accessible server side. MADNESS. I will be accepting Brian's answer as he mentioned the fix before anyone else.
public ITemplate Content
which then you render to the UI like:
Label label = new Label();
this.Content.InstantiateIn(label);
//Render label
EDIT: Make sure the template also defines
[TemplateInstance(TemplateInstance.Single)]
as this allows you to access the controls within the template directly.
You should try to use this:
win_StatusFilter.FindControl("btn_Test") // this will be a Control
win_StatusFilter.FindControl("btn_Test") as Button // this will be a Button if control found, otherwise it will be null.
Otherwise you should define some properties for your control, like in this article:
http://msdn.microsoft.com/ru-ru/library/36574bf6%28v=VS.90%29.aspx
Update:
According the remarks in this article about ContentTemplate property of the UpdatePanel:
http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.contenttemplate(v=VS.90).aspx
you can get controls from ContentTemplate because of TemplateInstanceAttribute value (UpdatePanel.ContentTemplate has the TemplateInstance.Single).
So you should only use this code:
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate Content
More information at:
http://msdn.microsoft.com/ru-ru/library/system.web.ui.templateinstanceattribute(v=VS.90).aspx

Adding custom valiadtion to ASP.NET controls

We're trying to build a simple asp control for some clients where they can just drop in a single block -
i.e.
<captcha:CaptchaControl ID="CaptchaControl1"
runat="server"
Server="http://localhost:51947/"
/>
and have it render the control. The catch is that I can't get this to include custom validation. Right now I'm using the RenderContents function to display the layout of the control itself as well as hook it up the to Javascript. The problem is that I don't know how to get custom validation to fire when used as part of a control.
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(#"
<script type=""text/javascript"" src=""http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js""></script>
<link rel=""stylesheet"" type=""text/css"" href=""/Layout/CaptchaLayout.css"" />
//etc
<asp:Textbox id=""text1"" runat=""server"" text=""""></asp:Textbox>
<asp:CustomValidator id=""CustomValidator2"" runat=""server""
ControlToValidate = ""text1""
ErrorMessage = ""You must enter at least 8 characters!""
ClientValidationFunction=""validateLength"" >
</asp:CustomValidator>"
);
}
Any suggestions for a better way to do this?
Oogh, I would definitely not recommend your approach. It's very brittle and difficult to maintain, and depending on how your control is used, I'm not even sure that you can output more asp tags and have them processed properly.
Why don't you just inherit your custom control from Panel, and then in the Init or Load event handlers, add the textbox and custom validator to it? Roughly:
public class MyControl : Panel
{
public MyControl()
{
}
protected override void OnInit(EventArgs e)
{
ScriptManager.RegisterScript( ... Google script, CSS, etc. ... );
TextBox txt = new TextBox();
txt.ID = "text1";
this.Controls.Add(txt);
CustomValidator vld = new CustomValidator();
vld.ControlToValidatre = "text1";
vld.ID = "validator1";
this.Controls.Add(vld);
}
}
Your CustomValidator doesn't work because ASP.NET has no idea it's there. You are basically just dumping that output to the response... ASP.NET is not interpreting it.
It seems to me that this is a perfect situation for a User Control rather than a Custom Control. Just drop that output string in its own .ASCX file.

Resources