БлогNot. WPF: фильтрация ввода в TextBox с помощью регулярного выражения

WPF: фильтрация ввода в TextBox с помощью регулярного выражения

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

Коротко: для нужного TextBox cоздать обработчик события PreviewTextInput с таким содержимым:

  e.Handled = !IsTextAllowed (e.Text);

Затем добавить в класс формы метод, фильтрующий ввод:

  private static bool IsTextAllowed (string text) {
   Regex onlyNumbers = new Regex ("[^0-9.-]+");
   return !onlyNumbers.IsMatch(text);
  }

Здесь разрешён ввод только цифр, на самом деле регулярное выражение может быть любой сложности.

Предполагается, что в начале файла .cs подключено пространство имён System.Text.RegularExpressions.

Можно фильтровать и другие события от компонент. Имена нужных обработчиков начинаются на Preview.

Опишем более подробно процесс создания проекта WPF C# (актуальная сборка Visual Studio 2019).

В окне Файл - Создать - Проект... выберем нужный тип приложения:

Выбор типа проекта "Приложение WPF (.NET Framework)"
Выбор типа проекта "Приложение WPF (.NET Framework)"

Нажав "Далее", настроим путь к проекту:

Настройка нового проекта
Настройка нового проекта

Нажав "Создать", получаем пустой проект. Вид по умолчанию окна для разработки будет таким:

Окна проекта WPF (вид по умолчанию)
Окна проекта WPF (вид по умолчанию)

Получить стандартный вид можно, выполнив команду меню Окно - Сброс макета окон.

  • 1 - Обозреватель решений.
  • 2 - Визуальный редактор (конструктор) формы, в который можно перетаскивать компоненты из панели элементов. Нужно учесть, что конструктор обычно жёстко привязывает элементы формы к пиксельным координатам на ней и ручная разметка с помощью XAML зачастую предпочтительнее.
  • 3 - Именно в этой области разметка пишется "вручную". Сделанные изменения немедленно отображаются к конструкторе и наоборот для элементов, которые мы перетащили в область 2, формируется разметка. Также в любой момент доступно окно свойств (правая кнопка на элементе в области 2, команда "Свойства"), где тоже можно изменять настройки элементов (как в Windows Forms).
  • 4 - Свёрнутая Панель элементов.
  • 5 - Свёрнутое окно Свойства.

В области 3 заменим содержимое по умолчанию следующей разметкой:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d" Width="800" Height="600" MinWidth="350" MinHeight="200" 
        WindowStartupLocation="CenterScreen" Title="Простые множители">
    <DockPanel Height="Auto" Width="Auto" LastChildFill="True">
        <TextBlock DockPanel.Dock="Top" Width="Auto" Margin="5" Padding="0,5">
            Простые множители натурального числа N
        </TextBlock>
        <StackPanel DockPanel.Dock="Top" Width="Auto" Orientation ="Horizontal">
            <Label Content="N="/>
            <TextBox Name="textBox1" Width="100" Margin="5" Padding="5"
                 TextWrapping="NoWrap" MaxLines="1" MaxLength="9" 
                 PreviewTextInput="textBox1_PreviewTextInput" 
                 GotKeyboardFocus="textBox1_GotKeyboardFocus" 
                 LostMouseCapture="textBox1_LostMouseCapture" 
                 LostKeyboardFocus="textBox1_LostKeyboardFocus" />
            <Button Content="Выполнить" Width="Auto" Margin="5" Padding="5"
                HorizontalAlignment="Left" VerticalAlignment="Center" 
                Name="button1" Click="button1_Click" />
            <Button Width="Auto" Margin="5" Padding="5"
                HorizontalAlignment="Left" VerticalAlignment="Center" 
                Name="button2" Click="button2_Click">Очистить</Button>
        </StackPanel>
        <TextBox Name="textBox2" Width="Auto" Margin="5" Padding="5"
                 TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" 
                 AcceptsReturn="True" 
                 HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    </DockPanel>
</Window>

Она показывает достаточно типовой подход для быстрой разработки интерфейсов WPF-приложений: DockPanel на всю форму как основной элемент окна, в него вложены компоненты со свойствами DockPanel.Dock="Top" и Width="Auto", последний элемент занимает всё оставшееся место за счёт указания в теге DockPanel атрибута LastChildFill="True".

Если некоторые элементы требуется сгруппировать по горизонтали, для этого подходит вложенный элемент StackPanel с атрибутом Orientation ="Horizontal".

В области 2 сделаем двойной клик по кнопке "Выполнить", откроется пустая функция вида

private void button1_Click (object sender, RoutedEventArgs e) {
 //Вместо этой строки можно писать код!
}

Того же результата можно было добиться, щёлкнув на элементе правой кнопкой мыши, выбрав команду Свойства, затем в окне свойств нажав кнопку с "молнией" ϟ (Обработчики событий) и выполнив двойной клик в строке обработчика события Click.

Вот полный код для кнопки выполнения:

  private void button1_Click (object sender, RoutedEventArgs e) {
   uint n = 0;
   if (!UInt32.TryParse (textBox1.Text, out n) || n < 2) {
    MessageBox.Show ("Введите положительное целое число больше 1.");
    button2_Click (this, e);
    return;
   }
   var numbers = primeFactors (n);
   if (numbers.Count < 1) {
    MessageBox.Show (String.Format("Неизвестная ошибка с числом {0}",n));
    button2_Click (this, e);
    return;
   }
   else if (numbers.Count == 1) {
    textBox2.Text += n.ToString() + " - простое число" + Environment.NewLine;
   }
   else {
    textBox2.Text += "Число = " + n.ToString ();
    textBox2.Text += "; простые множители = " + string.Join (", ", numbers);
    uint prod = 0;
    string str = "";
    foreach (var val in numbers) {
     str += val.ToString () + "*";
     prod = prod == 0 ? val : prod * val;
    }
    str = str.Remove (str.Length - 1, 1) + "=";
    textBox2.Text += "; проверка: " + str + prod.ToString () + Environment.NewLine;
   }
   textBox2.ScrollToEnd ();
   n++;
   if (n.ToString ().Length <= textBox1.MaxLength)
    textBox1.Text = n.ToString ();
  }

Аналогично создадим обработчик клика по второй кнопке:

  private void button2_Click (object sender, RoutedEventArgs e) {
   textBox1.Clear ();
   textBox1.Focus ();
   textBox2.Clear ();
  }

Обратившись к свойствам первого текстбокса (с именем Name="textBox1") найдём в списке событий PreviewTextInput, выполним двойной клик по пустому полю и вставим в появившуюся функцию первую строчку кода из статьи.

Потом в файле MainWindow.xaml.cs (из окна конструктора к нему всегда можно перейти командой верхнего меню Вид - Код) добавим показанный в начале статьи метод IsTextAllowed. Осталось написать основной метод программы primeFactors, формирующий для введённого числа список его простых множителей (или определяющий, что само введённое число - простое; мы выбрали это в качестве модельной задачи). Второй текстбокс служит для ведения лога.

  private List <uint> primeFactors (uint n) {
   var numbers = new List<uint> ();
   uint f = 2;
   if (n == 1) numbers.Add (1);
   else {
    while (true) {
     if (n % f == 0) {
      numbers.Add (f);
      n /= f;
      if (n == 1) return numbers;
     }
     else f++;
    }
   }
   return numbers;
  }

Выделять содержимое TextBox при переходе в него (получении фокуса) без удаления возможного имеющегося выделения пользователя можно примерно таким набором обработчиков:

  private void textBox1_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
   if (textBox1.SelectionLength == 0) textBox1.SelectAll();
  }
  private void textBox1_LostMouseCapture(object sender, MouseEventArgs e) {
   if (textBox1.SelectionLength == 0) textBox1.SelectAll();
   textBox1.LostMouseCapture -= textBox1_LostMouseCapture;
  }
  private void textBox1_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
   textBox1.LostMouseCapture += textBox1_LostMouseCapture;
  }

Приложение готово, его можно собирать и запускать.

Приложение в работе (скриншот)
Приложение в работе (скриншот)

 Скачать этот проект WPF в архиве .zip, развернуть в новую папку (10 Кб)

10.09.2024, 20:37 [111 просмотров]


теги: программирование учебное c# xml

К этой статье пока нет комментариев, Ваш будет первым