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 (вид по умолчанию)
Получить стандартный вид можно, выполнив команду меню Окно - Сброс макета окон.
- 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 просмотров]