views:

349

answers:

2

I need to create a WinForms textbox that allows decimal text exclusive-or integer text. Also, I don't wish to be required to specify the length of the text in the mask; the user should be able to enter as many characters as he wants, as long as the text fits the decimal or integer mold. However, the MaskedTextBox doesn't allow variable-length masking, as far as I know; I can't find a pre-existing control that does this, either.

Advice? I suppose I could inherit TextBox, override OnKeyPress and do the work there, but I don't know whether a pre-existing control would do things more gracefully.

A: 

the NumericUpDown control has some built in decimal/integer parsing behavior - sounds like it might be what you're looking for. Of course, you end up with the updown controls on the text box too.

Lenny
I took a look at that control. There's a way to hide the spinners (the up/down buttons), but it doesn't look very clean.NumericUpDown nud;...nud.Controls[0].Hide();
lolwhat
Lenny! Welcome to SO. Hans here.
Hans Passant
A: 

Here's a solution. It's not perfect - it may eat control characters in certain cases, and it doesn't cleanly handle pasting - but it works well enough!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace WinFormsTest
{
    public partial class MaskedTextBox : TextBox
    {
        public enum EntryTypeEnum
        {
            Any,
            Integer,
            Decimal
        }

        [DefaultValue(EntryTypeEnum.Any)]
        public EntryTypeEnum EntryType { get; set; }

        public MaskedTextBox()
        {
            InitializeComponent();
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            var keyIsValid =
                (EntryType == EntryTypeEnum.Any)
                || char.IsControl(e.KeyChar)
                || isValid(Text + e.KeyChar);
            e.Handled = !keyIsValid;
            base.OnKeyPress(e);
        }

        protected override void OnValidating(CancelEventArgs e)
        {
            e.Cancel = !isValid(Text);
            base.OnValidating(e);
        }

        protected bool isValid(string textToValidate)
        {
            switch (EntryType)
            {
                case EntryTypeEnum.Any:
                    break;

                case EntryTypeEnum.Decimal:
                    {
                        decimal result;
                        if (!decimal.TryParse(textToValidate, out result))
                        {
                            return false;
                        }
                    }
                    break;

                case EntryTypeEnum.Integer:
                    {
                        int result;
                        if (!int.TryParse(textToValidate, out result))
                        {
                            return false;
                        }
                    }
                    break;
            }

            return true;
        }
    }
}
lolwhat