2015-09-14 3 views
2

Я пытаюсь, чтобы текстовое поле принимало только определенные символы.WPF - MVVM Текстовое поле ограничено конкретными символами

Мой TextBox обязан следующее:

private string _CompanyID; 
    public string CompanyID 
    { 
     get { return _CompanyID; } 
     set 
     { 
      _CompanyID = UniversalHelpers.sReturnCorrectColumnName(value); 
      OnPropertyChanged("CompanyID"); 
     } 
    } 

Где это функция, которая вызывается:

public static string sReturnCorrectColumnName(string sInput) 
    { 
     if(!string.IsNullOrWhiteSpace(sInput)) 
      return Regex.Replace(sInput, @"[^a-zA-Z]", string.Empty).ToUpper(); 
     else 
      return sInput; 
    } 

(я позволяю только-Z & A-Z, ничего).

Наконец мой TextBox выглядит следующим образом:

<TextBox Text="{Binding ExcelBindings.CompanyID, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" /> 

То, что я не понимаю, что пользователь может еще что-то, что он хочет писать, даже если мой режим установлен в TwoWay.

Что я делаю неправильно?

+0

Да, это не работает хорошо.Внедрите IDataErrorInfo и/или INotifyDataErrorInfo и просто отметьте экземпляр с ошибкой, когда они содержат неправильные символы. – Will

+0

Пользовательский интерфейс не будет автоматически обновляться с изменениями, внесенными вами при вводе пользователем. Он сохранен правильно (только a-z & A-Z), но ваш пользовательский интерфейс не будет автоматически обновляться даже с привязкой TwoWay. – rmn36

+0

Есть ли способ обновить пользовательский интерфейс без регистрации нового свойства Dependency? –

ответ

2

Вы должны использовать элемент пользовательского интерфейса там, ограничивающее вход на вид на стороне, используя «классические» решения, как слушатели изменения.

Например, вы можете просто создать простой подтип TextBox, который переопределяет метод OnPreviewTextInput. Там вы можете решить, когда какой-то вход должен пройти, или когда вы хотите его предотвратить.

Например, это обычай TextBox, который принимает только символы из ASCII алфавита:

public class AlphabetTextBox : TextBox 
{ 
    private static readonly Regex regex = new Regex("^[a-zA-Z]+$"); 

    protected override void OnPreviewTextInput(TextCompositionEventArgs e) 
    { 
     if (!regex.IsMatch(e.Text)) 
      e.Handled = true; 
     base.OnPreviewTextInput(e); 
    } 
} 

Конечно, вы можете также сделать регулярное выражение свойство текстового поля и позволяют людям, чтобы установить его от XAML. Таким образом, вы получите очень многоразовый компонент, который вы можете использовать для различных приложений.

1

Я делаю это с событием PreviewtextInput. У меня есть общее событие, используемое для нескольких TextBox, которые принимают регулярное выражение из таблицы конфигурации, но в этом примере у меня есть жестко закодированное регулярное выражение.

private void GenericTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) 
{ 
    e.Handled = !IsTextAllowed(e.Text, @"[^a-zA-Z]"); 
} 

private static bool IsTextAllowed(string Text, string AllowedRegex) 
{ 
    try 
    { 
     var regex = new Regex(AllowedRegex); 
     return !regex.IsMatch(Text); 
    } 
    catch 
    { 
     return true; 
    } 
} 
0

Проблема в том, что люди последовательно вводят цифры, дураки.
Чтобы ввести «0,1», законную строку, вы должны ввести «0.», что не получается. Кроме того, повторно принятый ответ от @poke (что отлично), значение e.Text - это изменение в текстовое поле (нажатие клавиши).
Вы должны добавить это изменение в текущую строку текстового поля, а затем проверить строку конкатенированной кандидата и посмотреть, действительно ли это. Люди также wiley, поэтому они будут вставлять из буфера обмена, чтобы обойти ограничение.
С текстовым полем вы никогда не сможете заблокировать весь мусор, потому что в какой-то момент пользователю придется пройти через мусор, чтобы перейти к допустимой строке.
Таким образом, вы можете заблокировать незаконную запись символа с помощью e.Text или разрешить последовательный сбой. Но вам все равно придется проверять окончательную строку на достоверность.
Ниже приведен пример текстового поля, в котором пользователи могут вводить десятичное значение с максимальным количеством в 8 делений, но они все равно могут обмануть это, вставив его из буфера обмена.

//////////////////////// 
// REGEXTEXTBOX CLASS // 
//////////////////////// 


using System.Windows.Controls; // Textbox 
using System.Windows.Input; 
using System.Text.RegularExpressions; // Regex 

namespace MyNamespace 
{ 
    public class RegexTextBox : TextBox 
    { 
     private Regex _regex = null; 

     public Regex Regex 
     { 
      get { return _regex; } 
      set { _regex = value; } 
     } 


     /////////////////////////////////////////////////////////////////////// 
     // MEMBERS 

     protected override void OnPreviewTextInput(TextCompositionEventArgs e) 
     { 
      var prefix = "OnPreviewTextInput() - "; 
      logger.Debug(prefix + "Entering"); 

      string currentText = this.Text; 
      string candidateText = currentText + e.Text; 

      // If we have a set regex, and the current text fails, 
      // mark as handled so the text is not processed. 
      if (_regex != null && !_regex.IsMatch(candidateText)) 
      { 
       e.Handled = true; 
      }   

      base.OnPreviewTextInput(e); 
     } 

    } // end of class RegexTextbox 

} // end of MyNamespace 


///////////////////// 
// MAINWINDOW.XAML // 
///////////////////// 

//(Window class needs to know your namespace so it needs xmlns:myNamespace="clr-namespace:MyNamespace") 

<myNamespace:RegexTextBox 
x:Name="textboxPayToAmount" 
Text="{Binding PayToAmount}"> 
</myNamespace:RegexTextBox> 


//////////////////////// 
// MAINWINDOW.XAML.CS // 
//////////////////////// 

namespace MyNamespace 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      textboxPayToAmount.Regex = 
       new System.Text.RegularExpressions.Regex(@"^\d*(\.\d{0,8})?$"); 
     } 
    } 
} 
Смежные вопросы