Итак, вам нужен TextBox, который принимает:
- A Di git или цифры, разделенные запятыми и / или ...
- Диапазон токенов цифр, таких как
1-5
. - Каждая цифра / число должны находиться в диапазоне минимальных и максимальных значений.
Давайте создадим для этого собственный текстовый ящик.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace YourNamespace
{
[DesignerCategory("Code")]
public class PrintPageRangeTB : TextBox
{
public PrintPageRangeTB() : base() { }
//...
Переопределите OnKeyPress
способ принятия 0 - 9 , , и - в дополнение к Control
клавишам:
//...
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (!char.IsControl(e.KeyChar) &&
!char.IsDigit(e.KeyChar) &&
e.KeyChar != '-' &&
e.KeyChar != ',')
e.Handled = true;
}
//...
Переопределите метод OnTextChanged
, чтобы подтвердить ввод, вызвав функцию IsValidInput()
и удалить последний введенный символ всякий раз, когда функция возвращает false
:
//...
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (!IsValidInput())
SendKeys.SendWait("{BS}");
}
//...
IsValidInput()
Функция проверяет свойство Text
и обнаруживает любой недопустимый формат, используя RegEx. Также проверяет минимальные и максимальные значения.
//...
private bool IsValidInput()
{
var parts = Text.Split(new[] { '-', ',' },
StringSplitOptions.RemoveEmptyEntries);
var pages = parts
.Where(x => int.TryParse(x, out _)).Select(x => int.Parse(x));
return !parts.Any(x => x.Length > 1 && x.StartsWith("0")) &&
!Regex.IsMatch(Text, @"^-|^,|--|,,|,-|-,|\d+-\d+-|-\d+-") &&
!pages.Any(x => x < Min || x > Max);
}
//...
Добавьте свойства для назначения минимальных и максимальных значений, свойство, которое возвращает, имеет ли Text
допустимый формат, и свойство, которое возвращает выбранные числа. /pages..
//...
public int Min { get; set; } = 1;
public int Max { get; set; } = 1000;
[Browsable(false)]
public bool IsValidPageRange => TextLength > 0 && IsValidInput();
[Browsable(false)]
public IEnumerable<int> Pages
{
get
{
var pages = new HashSet<int>();
if (IsValidInput())
{
var pat = @"(\d+)-(\d+)";
var parts = Text.Split(new[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
foreach(var part in parts)
{
var m = Regex.Match(part, pat);
if (m != null && m.Groups.Count == 3)
{
var x = int.Parse(m.Groups[1].Value);
var y = int.Parse(m.Groups[2].Value);
for (var i = Math.Min(x, y); i <= Math.Max(x, y); i++)
pages.Add(i);
}
else if (int.TryParse(part.Replace("-", ""), out int v))
pages.Add(v);
}
}
return pages.OrderBy(x => x);
}
}
//...
Функция, которая соединяет выделение и разделяет их по умолчанию или переданному разделителю:
//...
public string PagesString(string separator = ", ") =>
string.Join(separator, Pages);
}
}
Перестроить, отбросить PrintPageRangeTB
из Toolbox , запустите и попробуйте.
Вот полный код.
Связанные