c# - una - Permitir solo alfanumérico en cuadro de texto
validar datos de texto en excel (13)
Tengo un cuadro de texto que no debe permitir la introducción de caracteres especiales.
El usuario puede introducir:
- Arizona
- Arizona
- 0-9
- Espacio
¿Cómo puedo hacer el evento KeyDown
para hacer esto?
Creo que vale la pena considerar hacer el filtrado en el evento TextChanged de TextBox. Puede crear una operación que elimine cualquier carácter no válido de su cadena de texto. Esto es un poco más complicado que bloquear el evento KeyDown.
Pero, creo que este es el camino a seguir, ya que no está bloqueando los mecanismos de manejo de eventos KeyDown / Up incorporados de WPF, así que copiar y pegar sigue funcionando. Estaría trabajando en un nivel más alto de abstracciones, así que creo que será más fácil averiguar qué está pasando.
La forma más sencilla de hacerlo sería incluir el Kit de herramientas extendido de WPF que tiene el control de hacer exactamente lo que está solicitando al especificar una máscara.
http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home
También mostrará la máscara en el cuadro de texto cuando ingrese, si es necesario.
(También tiene muchos otros controles útiles)
Logro esto con una propiedad de dependencia personalizada. Es reutilizable para cualquier control de TextBox
, es mucho más rápido y más eficiente de usar que la creación de eventos clave, y hace que mis archivos de código sean mucho más limpios.
Además, puede manejar otros métodos de entrada que no activan eventos clave, como pegar un valor en el TextBox usando el mouse.
El código para el DP personalizado se ve así:
// When set to a Regex, the TextBox will only accept characters that match the RegEx
/// <summary>
/// Lets you enter a RegexPattern of what characters are allowed as input in a TextBox
/// </summary>
public static readonly DependencyProperty AllowedCharactersRegexProperty =
DependencyProperty.RegisterAttached("AllowedCharactersRegex",
typeof(string), typeof(TextBoxProperties),
new UIPropertyMetadata(null, AllowedCharactersRegexChanged));
// Get
public static string GetAllowedCharactersRegex(DependencyObject obj)
{
return (string)obj.GetValue(AllowedCharactersRegexProperty);
}
// Set
public static void SetAllowedCharactersRegex(DependencyObject obj, string value)
{
obj.SetValue(AllowedCharactersRegexProperty, value);
}
// Events
public static void AllowedCharactersRegexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var tb = obj as TextBox;
if (tb != null)
{
if (e.NewValue != null)
{
tb.PreviewTextInput += Textbox_PreviewTextChanged;
DataObject.AddPastingHandler(tb, TextBox_OnPaste);
}
else
{
tb.PreviewTextInput -= Textbox_PreviewTextChanged;
DataObject.RemovePastingHandler(tb, TextBox_OnPaste);
}
}
}
public static void TextBox_OnPaste(object sender, DataObjectPastingEventArgs e)
{
var tb = sender as TextBox;
bool isText = e.SourceDataObject.GetDataPresent(DataFormats.Text, true);
if (!isText) return;
var newText = e.SourceDataObject.GetData(DataFormats.Text) as string;
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(newText.Trim(), re, RegexOptions.IgnoreCase))
{
e.CancelCommand();
}
}
public static void Textbox_PreviewTextChanged(object sender, TextCompositionEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(e.Text, re, RegexOptions.IgnoreCase))
{
e.Handled = true;
}
}
}
Y se usa así:
<TextBox Text="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged}"
local:TextBoxHelpers.AllowedCharactersRegex="a-zA-Z0-9/s" />
Manejar los eventos KeyDown o KeyPress es una forma de hacerlo, pero los programadores generalmente olvidan que un usuario todavía puede copiar y pegar texto no válido en el cuadro de texto.
Una forma algo mejor es manejar el evento TextChanged y eliminar los caracteres ofensivos allí. Esto es un poco más complicado, ya que debe realizar un seguimiento de la posición del cursor y restablecerla en el lugar apropiado después de cambiar la propiedad de Texto del cuadro.
Dependiendo de las necesidades de su aplicación, solo permitiría que el usuario escriba lo que quiera y luego marque el cuadro de texto (vuelva el texto en rojo o algo así) cuando el usuario intente enviarlo.
Me topé con esto en Silverlight y escribí algo como esto.
private string _filterRegexPattern = "[^a-zA-Z0-9]"; // This would be "[^a-z0-9 ]" for this question.
private int _stringMaxLength = 24;
private void _inputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(_filterRegexPattern))
{
var text = _inputTextBox.Text;
var newText = Regex.Replace(_inputTextBox.Text, _filterRegexPattern, "");
if (newText.Length > _stringMaxLength)
{
newText = newText.Substring(0, _stringMaxLength);
}
if (text.Length != newText.Length)
{
var selectionStart = _inputTextBox.SelectionStart - (text.Length - newText.Length);
_inputTextBox.Text = newText;
_inputTextBox.SelectionStart = selectionStart;
}
}
}
Sé que winForms tiene disponible un control MaskedTextBox, que le permite especificar exactamente este tipo de cosas. No sé WPF, así que no sé si está disponible allí, pero si lo está, haz eso. Es MUCHO más fácil que todo esto con pulsaciones de teclas y eventos, y más robusto también.
Solo quería agregar un código para aquellos que terminan aquí por búsqueda:
private void Filter_TextChanged(object sender, EventArgs e)
{
var textboxSender = (TextBox)sender;
var cursorPosition = textboxSender.SelectionStart;
textboxSender.Text = Regex.Replace(textboxSender.Text, "[^0-9a-zA-Z ]", "");
textboxSender.SelectionStart = cursorPosition;
}
Este es un filtro de cambio, por lo que maneja copiar y pegar, y preserva la posición del cursor para que el cambio de texto en el medio funcione correctamente.
Tenga en cuenta que utiliza el ''remitente'' para obtener el nombre del control, lo que permite que esta función se vincule a múltiples cuadros de texto, suponiendo que necesiten el mismo filtro. Puede vincular varios controles yendo a la sección de eventos de un control y seleccionando manualmente la función para el evento TextChanged.
Use una expresión regular para filtrar los otros personajes. O use los métodos Char.IsDigit, IsXXX para filtrar los caracteres no deseados. Muchas formas de hacer esto.
Actualización: Si debe usar KeyDown, entonces parece que también debe manejar KeyPressed y establecer obEventArgs.Handled = true para no permitir los caracteres. Vea el ejemplo en la página de MSDN de KeyDown
Actualización: Ahora que especifica que es WPF. El siguiente código permitirá que solo se ingresen caracteres az y AZ en el cuadro de texto. Extender según sea necesario ...
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}
Esto se romperá si copia y pega cosas en el cuadro de texto. Valide todo el texto una vez que el usuario deja el control o cuando hace clic en Aceptar / Enviar como dice MusicGenesis.
Utilice Asp.NET AJAX Control Toolkit
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
Y Utilice FilteredTextBoxExtender
<asp:TextBox ID="txt_gpf_no" runat="server" CssClass="textbox"
MaxLength="10"></asp:TextBox>
<asp:FilteredTextBoxExtender ID="FilteredTextBoxExtender_gpf_no" runat="server" Enabled="True"
TargetControlID="txt_gpf_no" FilterType="UppercaseLetters,LowercaseLetters,Custom" ValidChars="1234567890 ">
</asp:FilteredTextBoxExtender>
en la aplicación my.Net Framework 4.5 C #
private void txtRF_Register_Val_KeyDown(object sender, KeyEventArgs e)
{
//only enable alphanumeric
if (!(((e.KeyCode < Keys.NumPad0) || (e.KeyCode > Keys.NumPad9)) && ((e.KeyCode < Keys.A) || (e.KeyCode > Keys.E))))
{
e.SuppressKeyPress = false;
}
else
{
e.SuppressKeyPress = true;
}
}
solo el cuadro de texto alfanumérico WPF C #,
lo siento por mi inglés ... pero con este código para WPF, c #, solo permito alfanumérico
private void txtTraslado_TextChanged(object sender, KeyEventArgs e)
{
if (((e.Key < Key.NumPad0)||(e.Key > Key.NumPad9))&&((e.Key < Key.A)||(e.Key > Key.Z)))
{
e.Handled = true;
}
}
y su regExp podría verse como [0-9a-zA-Z] * para permitir solo caracteres alfanuméricos en inglés
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}