Tuesday, August 4, 2009

Making a parsable text box in .Net 3.5

Introduction

The standard WPF controls provided by the .Net 3.5 SP1 framework do not contain a range of controls like numerical text boxes. Very often developers need these text boxes to limit the user input to accept integers or floating point etc. I developed these controls while working on a hobby project of mine. While at it, I thought it would be nice to extend these controls to beyond numerical data types and in general, parse any text into strongly typed .Net objects. This article describes how to extend the library to target any .Net data type that you want to create ,starting from plain text input.

Note: Unless and until mentioned otherwise, we will referring to input that has to be parsed as a System.Double object. We will call its text counterpart as floating point representation.

Background

The objective is to get textboxes that accept a text input that can be parsed into a strongly typed .Net object. Now, most people will enter text character by character (possibly press back spaces, or cursor keys and edit/remove previously eneterd characters or add new characters at any location) and so it is not sufficient to intercept the TextInput event and check if Double.TryParse returns true or false. That said, we also want to prevent users from enetering characters that once entered will never allow the input to become a valid floating point number even if any characters are appended to their input. Also, we will like to notify them that they need to append characters that will make their input valid.

For example, in the following screenshot, the top row shows examples of input that can become valid (bottom row) after some specific characters are appended to the input.

MyControls

Some input can never be made valid, meaning no character combination can be appended to rectify it. Example, -1.2. -1.. -- 12p 12e-1. etc. We shall not allow the text box to reach such a state.

Since the main purpose of this article is to demonstrate how to extend this control, let's review its design in some detail. If I were to tell you to write a program to accept a string input character by character and determine if the input you have received so far constitutes a valid floating point number, chances are that you will start thinking in terms of a finite automata. Meaning you will define some states and jump from one state to other depending on some pre-defined (i.e., design time) rules. Some of these states would be final --meaning that if you are on it the input is valid, else it is invalid. While there is nothing wrong with this approach and you can build correct programs using this approach, the code will look a bit messy. Furthermore, if you were to extend this code to accept variations in the float representations (like accepting the thousand seperator or the exponential part then you will have to add new states, new jumps etc.

Now, let's utilize something known as a regular expression. Regular expression are equivalent to a finite automata --meaning for every finite automata there exists a regular expression (on the same set of alphabets) and vice versa. So, if we can define a regular expression for a valid floating point pattern, all we need is to find out if the input matches the regular expression. To do so, you will need to again write an automata code and the whole point will be defeated. But, some good people, have already written code to match any text against any regular expression and it is available under the System.Text.RegularExpressions namespace in .Net.

So first and foremost we need two regular expressions: one for patterns that are valid and one of the patterns for which a character combination exists, that when appended to it shall make it valid. For System.Double objects these can be:


See full detail: http://www.codeproject.com/KB/edit/ParsableTextBox.aspx