utilizando expresiones regulares para dni, correo, etc...
La forma más segura de validar una dirección de email, es mediante un proveedor de validación de dominios (ya sea online, o mediante una bd offline), pero a falta de esto, mejor que una expresión regular es más recomendable utilizar los miembros de la clase
System.Uri para validar la estructura/sintaxis de la dirección de e-mail ( puedes combinar esta metodología con una evaluación RegEx para cubrir otros aspectos de validación sobre el string, pero en mi opinión eso sería perder el tiempo, puesto que nada es 100% efectivo, y esto ya cubre varios aspectos importantes de validación de direcciones e-mail ):
/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Validates a mail address.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <example> This is a code example.
/// <code>
/// Dim isValid As Boolean = ValidateMail("Address@Gmail.com")
/// Dim isValid As Boolean = ValidateMail("mailto:Address@Gmail.com")
/// </code>
/// </example>
/// ----------------------------------------------------------------------------------------------------
/// <param name="address">
/// The mail address.
/// </param>
/// ----------------------------------------------------------------------------------------------------
/// <returns>
/// <see langword="true"/> if the mail address is valid, <see langword="false"/> otherwise.
/// </returns>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
public static bool ValidateMail(string address) {
if (!address.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase)) {
address = address.Insert(0, "mailto:");
}
if (!Uri.IsWellFormedUriString(address, UriKind.Absolute)) {
return false;
}
Uri result = null;
if (Uri.TryCreate(address, UriKind.Absolute, result)) {
return (result.Scheme == Uri.UriSchemeMailto);
} else {
return false;
}
}
/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Validates a mail address.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <example> This is a code example.
/// <code>
/// Dim isValid As Boolean = ValidateMail(New MailAddress("Address@Gmail.com"))
/// Dim isValid As Boolean = ValidateMail(New MailAddress("mailto:Address@Gmail.com"))
/// </code>
/// </example>
/// ----------------------------------------------------------------------------------------------------
/// <param name="address">
/// The mail address.
/// </param>
/// ----------------------------------------------------------------------------------------------------
/// <returns>
/// <see langword="true"/> if the mail address is valid, <see langword="false"/> otherwise.
/// </returns>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
public static bool ValidateMail(MailAddress address) {
return MailUtil.ValidateMail(address.Address);
}
El código original, este de aquí abajo, lo he extraido de mi framework comercial
Elektrokit para programadores de .NET (el cual lo puedes encontrar en mi firma, por si te interesa)...
Graphics g = //....aqui me he quedado porque en la funcion original se usaba
//un PaintEventArgs e como argumento y la línea de instrucción seguia ...e.Graphics.
Esto que voy a explicar
no te conviene hacerlo, tan solo me estoy limitando a responder a tu pregunta para aclararte la duda que tienes:
El objeto "e" es del tipo
Graphics, por ende, la función equivalente que estás buscando es
Control.CreateGraphics(), o bien
Graphics.FromHwnd() (ambas tienen el mismo efecto)
Te muestro un ejemplo de uso genérico que he elaborado con extensiones de método:
public static class ControlExtensions {
/// <summary>
/// Draws a solid border of the specified color with 1 pixel width around the bounds of the source <see cref="Control"/>.
/// </summary>
public static void DrawBorder(this Control sender, Color color) {
ControlExtensions.DrawBorder(sender, color, 1, ButtonBorderStyle.Solid, sender.ClientRectangle);
}
/// <summary>
/// Draws a solid border of the specified color and with around the bounds of the source <see cref="Control"/>.
/// </summary>
public static void DrawBorder(this Control sender, Color color, int width) {
ControlExtensions.DrawBorder(sender, color, width, ButtonBorderStyle.Solid, sender.ClientRectangle);
}
/// <summary>
/// Draws a border of the specified color, with and style around the bounds of the source <see cref="Control"/>.
/// </summary>
public static void DrawBorder(this Control sender, Color color, int width, ButtonBorderStyle style) {
ControlExtensions.DrawBorder(sender, color, width, style, sender.ClientRectangle);
}
/// <summary>
/// Draws a border of the specified color, with and style around the specified bounds of the source <see cref="Control"/>.
/// </summary>
public static void DrawBorder(this Control sender, Color color, int width, ButtonBorderStyle style, Rectangle bounds) {
switch (sender.GetType()) {
// You can implement here a custom case for selective painting...
// case typeof(TextBox):
// case typeof(RichTextBox):
// etc.
default:
using (Graphics g = sender.CreateGraphics()) { // or also: Graphics.FromHwnd(sender.Handle)
ControlPaint.DrawBorder(g, bounds,
color, width, style, // left
color, width, style, // top
color, width, style, // right
color, width, style); // bottom
}
break;
}
}
}
Modo de empleo:
myControl.DrawBorder(Color.Red, 1, ButtonBorderStyle.Solid);
Código original, escrito en VB.NET:
me gustaría que si un campo no pasa la validación, dicho campo(siendo textbox o combobox, o label para radiobutton o checkbox) cambiase de color(la letra en los labels y el borde de los textbox o combobox).
Para el tratamiento de validación de entrada en controles de edición (o Edit-controls) te conviene utilizar el componente
ErrorProvider, sin más, una vez lo hayas configurado de forma correcta (controlando las validaciones de cada campo/control) si un control no pasa la validación entonces el componente mostrará un icono (personalizable) que indicará un fallo de validación en "X" campo(s), y de esta manera evitarás tener que reinventar la rueda para ir intentando modificar el color de los bordes de todos los controles del Form en caso de fallo de validación...

lo único de lo que realmente me entero es de que le he pasado el control y que creo que no debe ser tan difícil...
Alguien me puede decir si voy por buen camino y qué es lo que me falta??
No, no vas por buen camino, por varios motivos...
La solución que considero más óptima ya te la expliqué más arriba, el componente
ErrorProvider, y todo lo que voy a decir desde este momento hasta el final del post no contribuye a la solución recomendada, por que la solución más óptima para tus necesidades ya se te explicó cual es (insisto), ahora, con la intención de intentar enseñarte y que aprendas algo básico que te podría servir de ayuda, déjame explicarte que los controles por defecto de Microsoft/.NET Framework se renderizan a partir de los estilos de ventana (también conocidos como
Window Styles, y los estilos de ventana extendidos o
Extended Window Styles) y de los estilos visuales definidos para el tipo de control (a su vez, los estilos visuales del control están definidos por el tema visual/windows theme que esté actualmente activo en el sistema operativo), quienes controlan el aspecto resultante del control. Puedes aplicar un estilo de ventana y también un estilo visual de control específico, por ejemplo puedes asignarle el estilo visual de un button a un picturebox (todo esto de forma administrada), lo que literálmente convertirá el aspecto del control sin realizar mayor esfuerzo, e incluso puedes desactivar los estilos visuales en toda la aplicación, pero eso es otra historia...
Por si te interesa para el futuro:
Sigamos con las explicaciones...
Dependiendo del control en cuestión, éste puede requerir un tratamiento específico y "especial" para poder aplicarle personalizaciones de diseño como por ejemplo añadir un borde de un color específico, pues los controles se encargan de controlar por si mismos sus eventos de dibujado y con ello se encargan de administrar el cómo, el cuando, y el qué deben dibujar ( en general todos los controles exponen el evento
Control.Paint, pero otros controles disponen de varios eventos adicionales de dibujado, los que internámente administran los mensajes de ventana:
WM_PAINT,
WM_PRINTCLIENT, etc ), y en muchos controles la complejidad de "dibujado manual" aumenta considerablemente, por ejemplo en un
ListView, si queremos personalizar su diseño entonces deberemos encargarnos de administrar el dibujado del fondo o background, y de la rejilla o grid, las columnas, el texto de cada campo de cada fila y su posicionamiento/alineación, etc; son muchos factores a tener en cuenta.
Personalizar el diseño de un control no es un tema sencillo, se requiere entendimiento, pues de hecho es MUY denso (hay muchos conceptos que no he tratado para no alargar más las explicaciones, y otros tantos conceptos que ni conoceré), y sobre todo se necesita PRÁCTICA para comprender, por que tarde o tempranos las pasaremos canutas puesto que algunos controles no permiten una administración guiada o sencilla por parte del usuario para este tipo de personalizaciones... y tendremos que activar una propiedad conocida como
OwnerDraw y/o activar el
UserPaint para "obligar" a que el control deje de administrar el dibujado para darnos el relevo y encarganos nosotros, pero en algunos controles esto será ignorado internamente, y entonces deberemos recurrir a la API de Windows para administrar el dibujado del control, todo esto se debe a que la tecnología de
WindowsForms (a diferencia de WPF) no está pensada para satisfacer las necesidades exquisitas de este tipo de personalizaciones avanzadas de diseño de controles... el soporte es muy limitado en este aspecto.
Por último, y quizás lo más importante que debes saber despues de todo este rollo...
La forma en la que estás intentando dibujar un borde sobre un control, es incorrecta (a parte de estar usando el método
DrawRectangle que es bastante expensivo y esto puede generar flickering), por que como ya hemos aclarado previamente, los controles se encargan de administrar el cómo, el cuando, y el qué deben dibujar, esto quiere decir que si tú en un momento determinado "X" le modificas el borde al control, ese cambio no persistirá demasiado... ya que la próxima vez que el control vuelva a controlar su dibujado, éste desechará el cambio que le aplicaste (o mejor dicho, el borde que tu dibujaste se "limpiará"), esto puedes comprobarlo sin ir más lejos con un Button, cuando pasas el puntero del mouse por encima del button se disparan varios eventos del mouse y del foco, y con ello el botón se redibujará... y perderás el borde que hayas aplicado de la manera en la que lo estás intentando aplicar.
Para solucionar ese problema, tienes dos opciones, la primera y la más deficiente es seguir con el código que estabas escribiendo (o con el código que yo te mostré con las extensiones de método) y controlar desde tu Form todos y cada uno de los eventos de "X" control que impliquen un redibujado de ese control, para llamar al método encargado de dibujar el borde en cada redibujado (esto es muy ineficiente y no siempre dará el resultado esperado).
La segunda opción, la más óptima, sería heredar la clase del control para controlar el dibujado. Según el control que sea, podrá ser tan sencillo como ampliar la implementación de invalidación (u overriding) del método heredado
Control.OnPaint(), en otros casos hará falta hacer lo mismo en otros métodos heredados relacionados con el dibujado, y en los casos más tediosos o quizás "complejos" deberemos procesar manualmente los mensajes de dibujado de ventana mediante el método de procedimiento de ventana (
WndProc), y según la sofisticación que queramos obtener, adicionálmente recurrir a la API de Windows a las funciones
BeginPaint y
EndPaint para reducir el efecto de flickering... entre otras técnicas que también podemos combinar para el mismo propósito.
En fin, para acabar te muestro un ejemplo sencillo y básico de como se podría implementar la funcionalidad de modificar el color del borde de un control de tipo Button:
[DisplayName("MyExtendedButton")]
[Description("A extended Button control.")]
[DesignTimeVisible(true)]
[DesignerCategory("UserControl")]
[ToolboxBitmap
(typeof(Button
),
"Button.bmp")] [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Require)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
[DefaultProperty("Text")]
[DefaultEvent("Click")]
public sealed class MyExtendedButton : Button {
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Localizable(false)]
[Category("(Extended) Appearance")]
[Description("The border color of the control.")]
[DefaultValue
(typeof(Color
),
"ControlLight")] public Color BorderColor { get; set; }
[DebuggerNonUserCode()]
public MyExtendedButton() {
base.SuspendLayout();
base.SetStyle(ControlStyles.DoubleBuffer, true);
// base.SetStyle(ControlStyles.AllPaintingInWmPaint, ... );
// base.SetStyle(ControlStyles.ResizeRedraw, ... );
// base.SetStyle(ControlStyles.UserPaint, ... );
// base.SetStyle(ControlStyles.SupportsTransparentBackColor, ... );
base.ResumeLayout(performLayout: false);
}
[DebuggerStepThrough()]
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
}
[DebuggerStepThrough()]
protected override void OnPaintBackground(PaintEventArgs e) {
base.OnPaintBackground(e);
}
[DebuggerStepperBoundary()]
protected override void WndProc(ref Message m) {
base.WndProc(m);
switch (m.Msg) {
case 15: // WM_Paint
this.DrawBorder();
break;
}
}
[DebuggerStepperBoundary()]
private void DrawBorder() {
using (Graphics g = base.CreateGraphics()) {
ControlPaint.DrawBorder(g, base.ClientRectangle,
this.BorderColor, 1, ButtonBorderStyle.Solid, // left
this.BorderColor, 1, ButtonBorderStyle.Solid, // top
this.BorderColor, 1, ButtonBorderStyle.Solid, // right
this.BorderColor, 1, ButtonBorderStyle.Solid); // bottom
}
}
}
Código original, escrito en VB.NET:
PD: Logicamente ese código es un ejemplo, carente de muchas funcionalidades básicas, por ejemplo se podría adaptar para aplicar un color distitno en el caso de que el botón tenga foco o no lo tenga, o cuando está pulsado o no lo está.
Saludos.