2010-01-28 2 views
2

Вопрос:Silverlight Преобразование PlatformKeyCode в код символа

Есть хороший способ в Silverlight для перехвата нежелательных символов из вводимой в текстовое поле?

фона:

У меня есть текстовое поле, которое позволяет пользователю ввести имя файла. Я хотел бы исключить неправильные имена файлов из текстового поля. Некоторыми из этих символов являются:

  • '?'
  • «\»
  • «<»
  • «>»

Хотя Silverlight класс TextBox не поддерживает событие KeyPress, у него есть KeyDown и событие KeyUp, который может быть использован для извлекать символьную информацию, когда ключ вводится в текстовое поле. Он предоставляет их в качестве члена перечисления Key или может возвращать int для PlatformKeyCode.

Конечно, диапазон клавиш больше/отличается от диапазона символов - примером этого являются клавиши «F». Однако присутствие чего-то типа события KeyPress в Windows Forms свидетельствует о полезности возможности получения конкретной информации о символе.

Чтобы сделать доказательство концепции, что все может работать я жёстко значения PlatformKeyCode для нежелательных символов для моей платформы в обработчик событий и все работало ... но конечно это только моя платформа. Мне нужно убедиться, что эта реализация является агностикой платформы. Вот код, чтобы показать, как я хотел бы, чтобы работать:

private void theText_KeyDown(object sender, KeyEventArgs e) 
    { 
     int[] illegals = { 191, 188, 190, 220, 186, 222, 191, 56, 186}; 
     if (illegals.Any(i => i == e.PlatformKeyCode)) e.Handled = true; 
    } 
+0

Есть ли причина, что делает его это сложно? Было бы намного проще просто выделять нежелательные символы с регулярным выражением всякий раз, когда текст изменяется (событие TextChanged в TextBox). –

+0

Решение Хенрика звучит намного проще. Другая идея - объявить свойство для текста в текстовом поле и использовать проверку свойства, чтобы указать пользователю, какие символы недопустимы. – Johannes

+0

Спасибо, ребята, за ваш ответ. Я попытался объяснить вам решение в ответе ниже. – t3rse

ответ

2

Оба ответа (в комментариях) от Хенрик и Johannes содержит лучший ответ для сценария. Вместо того, чтобы думать как программист Windows Forms и захватывать конкретное ключевое событие, канонический подход в Silverlight заключается в использовании события TextChanged для удаления нежелательных символов из TextBox. A similar question, позволяющий вводить только текстовый ввод в TextBox, вызвал решение, которое было использовано.

Следующие примеры кода, подход, который я принял после прочтения комментариев, и она работает достаточно хорошо, чтобы удалить символы неуместные для записи:

private void fileNameTextBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     string illegalChars = @"?<>:""\/*|"; 
     fileNameTextBox.Text = String.Join("", fileNameTextBox.Text.Split(illegalChars.ToCharArray())); 
     fileNameTextBox.SelectionStart = fileNameTextBox.Text.Length; 
    } 
+0

+1 Я не знал, что вы можете удалить символы, используя метод Split. Это «t3rse» !! – Aligned

+0

да, но обратите внимание на это, потому что, поскольку строка интернализирована, вы, вероятно, закончите заполнение памяти маленькими бесполезными фрагментами строк, если вы введете много в этом текстовом поле, но, возможно, это нормально для вашего случая использования –

2
using System; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Interactivity; 

public class FilterTextBoxBehavior : Behavior<TextBox> 
{ 
    public readonly static DependencyProperty AllowAlphaCharactersProperty = DependencyProperty.Register("AllowAlphaCharacters", typeof(bool), typeof(FilterTextBoxBehavior), new PropertyMetadata(true)); 
    public bool AllowAlphaCharacters 
    { 
     get { return (bool)GetValue(AllowAlphaCharactersProperty); } 
     set { SetValue(AllowAlphaCharactersProperty, value); } 
    } 

    public readonly static DependencyProperty AllowNumericCharactersProperty = DependencyProperty.Register("AllowNumericCharacters", typeof(bool), typeof(FilterTextBoxBehavior), new PropertyMetadata(true)); 
    public bool AllowNumericCharacters 
    { 
     get { return (bool)GetValue(AllowNumericCharactersProperty); } 
     set { SetValue(AllowNumericCharactersProperty, value); } 
    } 

    public readonly static DependencyProperty AllowSpecialCharactersProperty = DependencyProperty.Register("AllowSpecialCharacters", typeof(bool), typeof(FilterTextBoxBehavior), new PropertyMetadata(true)); 
    public bool AllowSpecialCharacters 
    { 
     get { return (bool)GetValue(AllowSpecialCharactersProperty); } 
     set { SetValue(AllowSpecialCharactersProperty, value); } 
    } 

    public readonly static DependencyProperty DoNotFilterProperty = DependencyProperty.Register("DoNotFilter", typeof(string), typeof(FilterTextBoxBehavior), new PropertyMetadata(default(string))); 
    public string DoNotFilter 
    { 
     get { return (string)GetValue(DoNotFilterProperty); } 
     set { SetValue(DoNotFilterProperty, value); } 
    } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     if (AssociatedObject == null) { return; } 

     FilterAssociatedObject(); 
     AssociatedObject.TextChanged += OnTextChanged; 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
     if (AssociatedObject == null) { return; } 

     FilterAssociatedObject(); 
     AssociatedObject.TextChanged -= OnTextChanged; 
    } 

    private void OnTextChanged(object sender, TextChangedEventArgs e) { FilterAssociatedObject(); } 
    private void FilterAssociatedObject() 
    { 
     int cursorLocation = AssociatedObject.SelectionStart; 

     for (int i = AssociatedObject.Text.Length - 1; i >= 0; i--) 
     { 
      char c = AssociatedObject.Text[i]; 
      if (ValidChar(c)) { continue; } 

      AssociatedObject.Text = AssociatedObject.Text.Remove(i, 1); 
      cursorLocation--; 
     } 

     AssociatedObject.SelectionStart = Math.Min(AssociatedObject.Text.Length, Math.Max(0, cursorLocation)); 
    } 

    private bool ValidChar(char c) 
    { 
     if (!string.IsNullOrEmpty(DoNotFilter) && DoNotFilter.Contains(c)) { return true; } 
     if (!AllowAlphaCharacters && char.IsLetter(c)) { return false; } 
     if (!AllowNumericCharacters && char.IsNumber(c)) { return false; } 
     if (!AllowSpecialCharacters && Regex.IsMatch(c.ToString(), @"[\W|_]")) { return false; } 

     return true; 
    } 
}