Reputation: 1092
How to allow inputs to the textbox in this format only?
Upvotes: 1
Views: 1447
Reputation:
So you need a TextBox that accepts:
1-5
.Let's create a custom TextBox for that.
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() { }
//...
Override the OnKeyPress
method to accept 0-9, , and - in addition to the Control
keys:
//...
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar)
&& !char.IsDigit(e.KeyChar)
&& e.KeyChar != '-'
&& e.KeyChar != ',')
e.Handled = true;
else
base.OnKeyPress(e);
}
//...
Override the OnTextChanged
method to validate the input by calling the IsValidInput()
function and to delete the last entered character whenever the function returns false
:
//...
protected override void OnTextChanged(EventArgs e)
{
if (Text.Trim().Length > 0 && !IsValidInput())
SendKeys.SendWait("{BS}");
else
base.OnTextChanged(e);
}
//...
The IsValidInput()
function validates the Text
property and detects any invalid format using RegEx. Also checks for the minimum and maximum values.
//...
private bool IsValidInput() => IsValidInput(Text);
private bool IsValidInput(string Input)
{
var parts = Input.Split(new[] { '-', ',' },
StringSplitOptions.RemoveEmptyEntries);
var pages = parts
.Where(x => int.TryParse(x, out _)).Select(x => int.Parse(x));
return Input.Trim().Length > 0
&& pages.Count() > 0
&& !parts.Any(x => x.Length > 1 && x.StartsWith("0"))
&& !Regex.IsMatch(Input, @"^-|^,|--|,,|,-|-,|\d+-\d+-|-\d+-")
&& !pages.Any(x => x < Min || x > Max);
}
//...
Add properties to assign the minimum and maximum values, a property that returns whether the Text
has a valid format, and a property that returns the selected numbers/pages..
//...
public int Min { get; set; } = 1;
public int Max { get; set; } = 1000;
[Browsable(false)]
public bool IsValidPageRange => 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);
}
}
//...
A function that joins the selection and separate them by the default or the passed separator:
//...
public string PagesString(string separator = ", ") =>
string.Join(separator, Pages);
}
}
Rebuild, drop a PrintPageRangeTB
from the Toolbox, run and try.
Here's the complete code.
Related
Upvotes: 1
Reputation: 36596
As mentioned by NeutralHadle, one way is to use input masking to restrict the possible input.
Another approach is to run some validation logic when text is entered, for example by attaching an event handler to the Validating event. If the text is in a incorrect format you may then use a ErrorProviderControl to inform the user how to properly format the input. More details in this answer.
Upvotes: 0