×
Namespaces

Variants
Actions
(Difference between revisions)

Implementing numerical InputBox in Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search
symbianyucca (Talk | contribs)
(Symbianyucca -)
 
symbianyucca (Talk | contribs)
(Symbianyucca -)
Line 10: Line 10:
 
#  use the NumberInputBox just as you would use normal textboxe’s
 
#  use the NumberInputBox just as you would use normal textboxe’s
  
 +
[[File:Wp8 numberInput.png]]
  
 
== implementing the NumberInputBox the class ==
 
== implementing the NumberInputBox the class ==

Revision as of 15:47, 4 March 2013

In general you can implement numerical input box for WP8 by simply defining the InputScope to be "Number". this would generally give you keyboard only allowing number characters as well as minus sign & decimal separators, however it would not give you options on doing any other filtering.

This article is illustrating a bit simplified way on doing input filtering in a way that the input box input can be handled for both negative and positive integer & float numbers. Also simple way on showing the valid range is also illustrated. The example here, has been implemented in several Map examples stored in Windows Phone 8 Maps Examples project.

Generally to get the input to work as expected, you need to:

  1. implement NumberInputBox the class
  2. include the name space in your xaml file
  3. use the NumberInputBox just as you would use normal textboxe’s

Wp8 numberInput.png

implementing the NumberInputBox the class

To include new class into a project, you would simply right click the project, select “Add”->”New item” from the pop-up menu and then select “Class” from the list and gibe the class meaningful name. As we simply want to make inoutbox, we get it done lot easier by reusing implementations already available, thus we derive the new class from

public class NumberInputBox : TextBox

Then to enable different types of input, we define enumeration which is defining the available input types:

public enum InputType
{
Integer = 0,
IntegerPositive = 1,
Float = 2,
FloatPositive = 3,
}

Then we define internal variable for which we can set the input type into. Also we have internal variables for limiting the values for valid input, as well as Boolean variable which would be telling whether the current input is inside the defined range.

public InputType Type { get; set; }
public int MaxValue { get; set; }
public int MinValue { get; set; }
public bool ValueOk { get; set; }

Which after we can then implement the constructor for the class. Inside the constructor, we will need to set the input scope to make sure we get right keyboard for the input, as well as we need to set the callback for the TextChanged event. Which after we simply set default values for the internal variables, so make sure that they are always valid.

public NumberInputBox(): base()
{
TextChanged += TextChangedEvent;
this.InputScope = new InputScope()
{
Names = { new InputScopeName() { NameValue = InputScopeNameValue.Number } }
};
this.Type = NumberInputBox.InputType.Integer;
this.MaxValue = this.MinValue = 0;
ValueOk = false;
}

Then the actual filtering of the input happens inside the TextChangedEvent function. Inside the function, we simply take the current input, put it through our own parser, and then set it back to the visible text. After setting the value, we do check whether we have max/min values set, and if they are, we check the input range, and use color to indicate whether the value is inside the defined range.

private void TextChangedEvent(object sender, TextChangedEventArgs e)
{
this.Text = ParseDouble(this.Text);
this.SelectionStart = this.Text.Length;
 
if (this.MaxValue != this.MinValue)
{
double d;
if (double.TryParse(this.Text, out d))
{
if (d < this.MinValue || d > this.MaxValue)
{
this.ValueOk = false;
this.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
this.ValueOk = true;
this.Foreground = new SolidColorBrush(Colors.Black);
}
}
}
}

The parsing code is then really simple. It basically takes the whole input buffer, and removes any characters which are not allowed and then returns string which is only having allowed input characters. The buffer is simple looped through in for loop from first character until the last.

In each loop, first in the validations the first character is checked whether it contains minus sign, and this character is only allowed to be the first character, in any other place it will be ignored. Also if only positive input is allowed, then no minus sign is accepted in any position.

Second check is accepting any digit-characters at any position of the buffer.

And if the number input is in float mode, then the last check is allowing the buffer to contain single instance of decimal separator. Note that the decimal separator used inside the code depends on the locale used, the UI default separator might not match the one required by the code, thus, with this check, both dot and comma characters are allowed, but the returned buffer will only contain the decimal separator for the current locale.

String ParseDouble(string input)
{
if (input.Length > 0)
{
String outBut = "";
bool foundSeparator = false;
 
for (int i = 0; i < input.Length; i++)
{
if ((this.Type == NumberInputBox.InputType.Integer
|| this.Type == NumberInputBox.InputType.Float)
&& ((i == 0) && input[0] == '-'))
{
outBut = outBut + input[i];
}
else if ((input[i] >= '0' && input[i] <= '9'))
{
outBut = outBut + input[i];
}
else if (this.Type == NumberInputBox.InputType.Float
|| this.Type == NumberInputBox.InputType.FloatPositive)
{
if (foundSeparator == false)
{
string Sepa = CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
if (Sepa.Length > 0)
{
if (Sepa[0] == input[i] || '.' == input[i] || ',' == input[i])
{
outBut = outBut + Sepa[0];
foundSeparator = true;
}
}
}
}
}
return outBut;
}
else
{
return "";
}
}

Add NumberInputBox to your XAML

First you need to add the namespace to your XAML file, f.ex. if the class is defined under the AreaSelector namespace, then simple add following text into the header section of the XAML file.

xmlns:myns="clr-namespace:AreaSelector"

Then to use the control, instead of using textbox tags you would be using myns:NumberInputBox tags instead. For example if you wish to have input boxes for latitude and longitude values, you could do it as follows:

<myns:NumberInputBox x:Name="LatitudeBox" Type="Float" MaxValue="90" MinValue="-90"/>
<myns:NumberInputBox x:Name="LongittudeBox" Type="Float" MaxValue="180" MinValue="-180"/>
243 page views in the last 30 days.