TipVisor
TipVisor

Reputation: 1092

How to TextBox inputs of custom format?

How to allow inputs to the textbox in this format only?

text

Upvotes: 1

Views: 1447

Answers (2)

user10216583
user10216583

Reputation:

So you need a TextBox that accepts:

  • A Digit or digits separated by commas and/or...
  • Range of digits tokens like 1-5.
  • Each digit/number should be within the range of minimum and maximum values.

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.

SOQ61099950

Here's the complete code.


Related

  • IP4 TextBox. »

Upvotes: 1

JonasH
JonasH

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

Related Questions