Grazie per le risposte. Fuex - mi hai messo sulla giusta strada, ecco il codice finale che include un controllo TextBox esteso e un controllo esteso di RadioButtonList.
Per usarli, aggiungi questa dichiarazione alla pagina aspx:
<% @ Register TagPrefix="MYPREFIX" Namespace="MyNamespace" Assembly="MYASSEMBLY"% >
Quindi aggiungi il controllo alla pagina in questo modo:
Controllo TextBox esteso:
< MYPREFIX: ExtendedTextBox ID="HomePhone" LabelText="Numero di telefono" CssClass="width_normal" LabelCssClass="width_normal" ValidatorCssClass="width_normal"
Obbligatorio="true" RequiredMessage="Il nome è obbligatorio" DataType="Intero" runat="server" > < / MYPREFIX: ExtendedTextBox >
- Se viene specificato solo CssClass , i controlli label e validator erediteranno questa classe.
- Le classi css Label e validator possono essere specificate singolarmente utilizzando LabelCssClass e ValidatorCssClass .
- Puoi aggiungere un RequiredMessage per impostare il messaggio di convalida. Se questo non è specificato, il messaggio di convalida sarà ' LabelText è richiesto'
-
LabelText non è richiesto - se manca, l'asterisco 'richiesto' verrà posizionato accanto alla casella di testo
- Per impostazione predefinita, viene generato lo script di validazione lato client (quindi non è necessario impostare 'ClientScript' su true).
- DataType può essere specificato per convalidare un tipo di dati specifico. I valori supportati sono Email e Intero
Controllo RadioButtonList esteso:
< WVNZ: ExtendedRadioButtonList RepeatLayout="Flow" ID="WrittenContactPreference" LabelText="Preferenziale preferenza per i contatti scritti"
LabelCssClass="boldLabel" runat="server" Richiesto="falso" >
< asp: ListItem > E-mail < / asp: ListItem >
< asp: ListItem > Casa < / asp: ListItem >
< / WVNZ: ExtendedRadioButtonList >
Affinché i controlli funzionino, è necessario incorporare quanto segue in un assembly denominato "MYASSEMBLY" a cui fa riferimento il progetto in cui viene implementato il controllo:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyNamespace
{
public interface IExtendedControl
{
string ID { get; set; }
bool Required { get; set; }
string CssClass { get; set; }
Label lbl { get; set; }
string LabelText { get; set; }
string LabelCssClass { get; set; }
RequiredFieldValidator rfv { get; set; }
string RequiredMessage { get; set; }
string ValidatorCssClass { get; set; }
bool ClientScript { get; set; }
ControlCollection Controls { get; }
}
public static class ExtendedControlExtensions
{
public static void AddRequiredFieldValidator(this IExtendedControl control)
{
if (!control.RequiredMessage.IsNullOrEmpty())
{
control.rfv.ErrorMessage = control.RequiredMessage;
}
else
{
control.rfv.ErrorMessage = control.LabelText + " is required";
}
ConfigureAndAddValidator(control, control.rfv);
}
public static void ConfigureAndAddValidator(this IExtendedControl control, BaseValidator validator)
{
validator.ControlToValidate = control.ID;
validator.Display = ValidatorDisplay.Dynamic;
validator.CssClass = "validationMessage ";
if (!control.ValidatorCssClass.IsNullOrEmpty())
{
validator.CssClass += control.ValidatorCssClass;
}
else validator.CssClass += control.CssClass;
validator.EnableClientScript = control.ClientScript;
control.Controls.Add(validator);
}
public static void AddLabel(this IExtendedControl control, string controlCssClass = "")
{
control.lbl = new Label();
control.lbl.Text = control.LabelText;
if (control.Required)
{
control.lbl.Text += " <span class=\"requiredFieldIndicator\"> *</span>";
}
control.lbl.ID = "lbl" + control.ID;
//TODO: associate label with control - code below needs other fixes to work
//lbl.AssociatedControlID = this.ID;
string cssClassToUse;
if (!control.LabelCssClass.IsNullOrEmpty()) cssClassToUse = control.LabelCssClass;
else cssClassToUse = control.CssClass;
if (control.LabelText.IsNullOrEmpty())
{
control.lbl.CssClass = cssClassToUse + " form_field_empty_label ";
}
else
{
control.lbl.CssClass = cssClassToUse + " form_field_label " + controlCssClass;
}
}
}
public class ExtendedTextBox : TextBox, IExtendedControl
{
public string LabelText { get; set; }
public string LabelCssClass { get; set; }
public bool Required { get; set; }
public string RequiredMessage { get; set; }
public string DataType;
public string DataInvalidMessage;
public string ValidatorCssClass { get; set; }
public bool ClientScript { get; set; }
public Label lbl { get; set; }
public RequiredFieldValidator rfv { get; set; }
private CompareValidator cv;
private RegularExpressionValidator rev;
private bool IsRegExpValidator;
protected override void OnInit(EventArgs e)
{
rfv = new RequiredFieldValidator();
ClientScript = true;
this.AddLabel();
if (Required)
{
this.AddRequiredFieldValidator();
}
if (!DataType.IsNullOrEmpty())
{
switch (DataType)
{
case "Email":
IsRegExpValidator = true;
AddRegExValidator(DataType);
break;
default:
AddCompareValidator(DataType);
break;
}
}
}
private void AddCompareValidator(string DataType)
{
cv = new CompareValidator();
cv.Operator = ValidationCompareOperator.DataTypeCheck;
switch (DataType)
{
case "Integer":
cv.Type = ValidationDataType.Integer;
cv.ErrorMessage = "Please enter a numeric value";
break;
default:
break;
}
if (!this.DataInvalidMessage.IsNullOrEmpty())
{
cv.ErrorMessage = this.DataInvalidMessage;
}
this.ConfigureAndAddValidator(cv);
}
private void AddRegExValidator(string DataType)
{
// for regex explanation see http://www.codeproject.com/Articles/22777/Email-Address-Validation-Using-Regular-Expression
const string MatchEmailPattern =
@"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
+ @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?
[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
+ @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?
[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
+ @"([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$";
rev = new RegularExpressionValidator();
switch (DataType)
{
case "Email":
rev.ValidationExpression = MatchEmailPattern;
rev.ErrorMessage = "Please enter a valid email address";
break;
default:
break;
}
if (!this.DataInvalidMessage.IsNullOrEmpty())
{
rev.ErrorMessage = this.DataInvalidMessage;
}
this.ConfigureAndAddValidator(rev);
}
protected override void Render(HtmlTextWriter w)
{
lbl.RenderControl(w);
base.Render(w);
if (Required)
{
rfv.RenderControl(w);
}
if (!DataType.IsNullOrEmpty())
{
if (IsRegExpValidator)
rev.RenderControl(w);
else
cv.RenderControl(w);
}
}
}
public class ExtendedRadioButtonList : RadioButtonList, IExtendedControl
{
public string LabelText { get; set; }
public string LabelCssClass { get; set; }
public bool Required { get; set; }
public string RequiredMessage { get; set; }
public string ValidatorCssClass { get; set; }
public bool ClientScript { get; set; }
public Label lbl { get; set; }
public RequiredFieldValidator rfv { get; set; }
protected override void OnInit(EventArgs e)
{
rfv = new RequiredFieldValidator();
ClientScript = true;
this.CssClass = "radioButtonList";
this.AddLabel(this.CssClass);
if (Required)
{
this.AddRequiredFieldValidator();
}
}
protected override void Render(HtmlTextWriter w)
{
lbl.RenderControl(w);
base.Render(w);
if (Required)
{
rfv.RenderControl(w);
}
}
}
}
Il modulo può quindi essere disposto utilizzando il seguente markup:
<fieldset id="PersonalDetails" >
<legend>Personal Details</legend>
<div class="form_row">
<p>
<strong>Name</strong></p>
<div class="form_field">
<MYPREFIX:ExtendedTextBox ID="PreferredTitle" LabelText="Title" CssClass="width_x-small"
LabelCssClass="width_x-small" ValidatorCssClass="width_x-small" runat="server"
Required="false">
</MYPREFIX:ExtendedTextBox>
</div>
<div class="form_field">
<MYPREFIX:ExtendedTextBox ID="FirstName" LabelText="First" CssClass="required width_small"
ValidatorCssClass="width_small" runat="server" Required="true" RequiredMessage="First name is required">
</MYPREFIX:ExtendedTextBox>
</div>
<div class="form_field">
<MYPREFIX:ExtendedTextBox ID="LastName" LabelText="Last" CssClass="width_small" runat="server"
Required="true" RequiredMessage="Last name is required">
</MYPREFIX:ExtendedTextBox>
</div>
</div>
</fieldset>
E quando il seguente foglio di stile viene aggiunto alla pagina dovrebbe funzionare bene. Lo sto utilizzando insieme a JQuery Datepicker, quindi se lo utilizzi, lo styling sarà fatto per il widget datepicker
fieldset legend
{
font-size: 20px;
padding: 16px 0px;
}
.form_row
{
margin-bottom: 10px;
}
.form_field
{
display: inline-block;
vertical-align: top;
}
.form_field input, textarea
{
font-weight: normal !important;
display: block;
margin-bottom: 2px;
}
.form_field .radioButtonList
{
display: block;
}
.form_field .radioButtonList input
{
display: inline;
vertical-align: middle;
margin-bottom: 5px;
}
.form_field .radioButtonList label
{
display: inline;
vertical-align: middle;
margin-left: 5px;
}
.form_field .radioButtonList .validationMessage
{
float: right;
clear: both;
vertical-align: middle;
margin-left: 5px;
}
.form_field.datepicker input
{
display: inline;
float: left;
}
.form_field .datepicker
{
display: inline;
float: left;
vertical-align: middle;
}
.form_field .ui-datepicker-trigger
{
display: inline;
float: left;
margin-left: 5px;
vertical-align: middle;
}
.form_field.datepicker .validationMessage
{
clear: both;
}
.ui-datepicker .ui-datepicker-title select
{
font-size: 0.9em;
min-width: 0;
}
thead th.ui-datepicker-week-end:first-child
{
font-size: 1em;
}
table.ui-datepicker-calendar tr:first-child td
{
font-size: 1em;
}
.form_field .form_field_label
{
color: #777777;
display: block;
font-size: 11px;
font-weight: normal;
line-height: inherit;
float: none;
}
.form_field_label.radioButtonList
{
margin-bottom: 8px;
}
.form_field_empty_label .requiredFieldIndicator
{
display: inline;
font-size: 11px;
vertical-align: middle;
}
.form_field label
{
color: #777777;
display: block;
font-size: 11px;
float: none;
}
.boldLabel
{
font-size: 12px;
font-weight: bold;
color: #333333;
margin-top: 8px;
margin-bottom: 12px;
}
.requiredFieldIndicator
{
color: Red;
}
/* general widths */
.width_x-small
{
width: 25px !important;
}
.width_small
{
width: 75px !important;
}
.width_normal
{
width: 150px !important;
}
.width_large
{
width: 200px !important;
}
.width_x-large
{
width: 275px !important;
}
.width_xx-large
{
width: 350px !important;
}
.validationMessage
{
color: Red;
font-size: 11px;
float: left;
}
#body-copy input.ui-formwizard-button
{
cursor: pointer;
font-size: 1.5em;
}
Intendo mettere i dettagli più completi di questa soluzione su un blog o in un progetto di codice da qualche parte quando avrò tempo in modo che possa essere sviluppato open source in un set completo di controlli. Se qualcuno vuole farlo nel frattempo, non esitare a farlo e per favore pubblica un link qui per aiutare altri sviluppatori.
Saluti