Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Mobile numeric up/down control

0.00/5 (No votes)
19 May 2008 1  
A simple, re-usable, mobile numeric up/down control that supports decimal places, and min/max.

Introduction

If you've developed a mobile .NET application before, you've most likely noticed that the standard numeric up/down control doesn't provide all of the functionality that you've become accustomed to with the full/desktop version of .NET. If you need some of this missing functionality, you've got a number of options, but they usually involve money or bloated control libraries, or sometimes they just don't work like you'd prefer.

Using the code

There isn't a whole lot to using the control... just drag it onto your form, and set a few of the control's properties, like so (sorry about the MS-Paint quality edits):

designer.PNG

Figure 1 - Designer properties

Setting the DecimalPlaces property will do just what you'd expect - it'll update the number of decimal places shown, as you can see here:

no_validation.PNG

Figure 2 - Example of DecimalPlaces in use

One thing to think when using this control is the EnforceMinMax property. If it's set to true, then the user can't modify the value to be outside of the set range. In the following screenshot, you'll notice that the user has reached the maximum value. As a result, the 'up' button has been disabled, and if the user were to hit the 'up' or 'down' key on their keyboard/SIP (Soft Input Panel), they wouldn't be able to go outside the set limits.

max.PNG

Figure 3 - Example of control at maximum

Additionally, if the user were to try to type in a new value higher than 100 or lower than 0, the value would be reset to the closest limit - e.g. if the user entered -5, in the case, the value would be reset to 0.

If you want to do your own validation, set the value of EnforceMinMax to false, and then listen for the Validating event from the control, and handle it however you want. Here's an example:

private void numericUpDown1_Validating(object sender, CancelEventArgs e)
{
    if ((numericUpDown1.Value > numericUpDown1.Maximum)
        || (numericUpDown1.Value < numericUpDown1.Minimum))
    {
        MessageBox.Show(string.Format(&quot;Value must be between '{0}' and '{1}'.&quot;, 
                        numericUpDown1.Minimum, numericUpDown1.Maximum));
        e.Cancel = true;
    }
}

Points of interest

If you look at the code, you'll notice that I've had to handle a number of events from the textbox and the up and down buttons:

private void btnDown_GotFocus(object sender, EventArgs e)
{
    OnGotFocus(EventArgs.Empty);
}
private void btnDown_LostFocus(object sender, EventArgs e)
{
    OnLostFocus(EventArgs.Empty);
}

In .NET CF 2.0, this is necessary because of some bug where custom user controls won't have the OnGotFocus, OnLoseFocus, OnValidating, or OnValidation methods called. I don't know why this is, and I don't care - I just want something that works:) So, to do that, I just listen for the corresponding events from all of the child controls, and use them to call the appropriate methods for the parent control.

Something I added that I'm pretty proud of (and also turned-out to be a little bit tricky) is the handling of the up and down key press events. Depending on where the focus is within the textbox, the up and down keys (as well as the up and down buttons) will increment the underlying value by the appropriate order. You don't get that on the desktop framework, because you have to specify the increment amount ahead of time. This is done by looking for the selection starts within the textbox, and then determining what sort of value we should use from incrementing/decrementing the underlying value:

private decimal GetFactor()
{
    int order = 0;
    string strValue = txt.Text;
    if (!string.IsNullOrEmpty(strValue)
        && (txt.SelectionStart > -1)
        /*&& (txt.SelectionLength > 0)*/)
    {
        int decimalIndex = strValue.IndexOf('.');
        if (decimalIndex == -1)
            decimalIndex = strValue.Length;

        if (decimalIndex > txt.SelectionStart)
            order = (decimalIndex - txt.SelectionStart) - 1;
        else
        {
            order = (decimalIndex - txt.SelectionStart);

            //should not be lower than the # of decimal places
            if ((-1 * order) > _decimalPlaces)
                order = (-1 * _decimalPlaces);
        }
    }

    return (decimal)Math.Pow(10.0, (double)order);
}

The mechanism that I use for keeping the underlying value and the visible value in sync is by listening for changes to the current value and updating the view, like so:

string formatString = &quot;{0:F&quot; + _decimalPlaces + &quot;}&quot;;
txt.Text = String.Format(formatString, _value);

And, parsing the typed input is done like this:

decimal? value = null;

try
{
    value = decimal.Parse(txt.Text);
}
catch (Exception)
{ }

if (value.HasValue)
{
    Value = value.Value;
}
else
{
    //overright value
    OnPropertyChanged(NumericUpDownProperties.Value);
}

That is, the typed value will only update the underlying value if it is valid - otherwise, we just refresh the previous value.

Finally, I want to mention that the numeric control implements the INotifyPropertyChanged interface - so you can use it for data-binding, just as you would any built-in MSFT Forms control.

The Future

I don't plan on doing too much more work with this (i.e., if you ask for an update, or a special version for VS2008, etc., I probably won't get around to it - at least, not promptly, anyway). My main motivation for this article was to put this control out on the web so perhaps somebody could make some use of it. If you have something constructive to say (e.g., suggestions on features to add, or way to improve code-readability, etc.) about this contribution, I'm all ears.

One thing, right off the bat, that could use some improvement, would be to figure-out a way to make the up and down buttons look better. The .NET CF standard buttons can't show images, so we're stuck with what we can type. If you try out the demo, you'll see that, as of right now, the up and down buttons are indicated by the '/\' and '\/' strings - which doesn't seem to look all that bad in my browser, but looks a little amateur on my device. Anyway, I'm open to suggestions on this matter.

History

  • 5-20-2008
    • Added screenshots
    • Added more code-snippets
    • Added more background information
    • Clarified my future involvement with this article in response to some misunderstanding from early commenters
  • 5-19-2008
    • Original article

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here