Auto-Formatting Text Inputs with MvvmCross and Value Converters
Value converters are one of the powerful features you get with an MVVM framework, and can be a lot of fun to experiment with. In my app I have many different types of text entry, and wanted to have an easy way to do automatic formatting for things like phone numbers and credit card numbers. Value converters to the rescue!
Achieving this behavior using value converters was actually quite trivial. Here’s an example of a phone number converter:
public class PhoneNumberValueConverter : MvxValueConverter
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var numbers = Regex.Replace(value.ToString(), @"\D", "");
if (numbers.Length <= 3)
return numbers;
if (numbers.Length <= 7)
return string.Format("{0}-{1}", numbers.Substring(0, 3), numbers.Substring(3));
return string.Format("({0}) {1}-{2}", numbers.Substring(0, 3), numbers.Substring(3, 3), numbers.Substring(6));
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Regex.Replace(value.ToString(), @"\D", "");
}
}
Yes, I realize this is just for US phone numbers, but that’s all I need for now. As text is entered into the field it will be formatted on the fly without impacting the value on the view model at all, which will always be stripped down to the digits. Here’s a similar converter for credit card numbers that splits the number into spaced groups of four:
public class CreditCardNumberValueConverter : MvxValueConverter
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var builder = new StringBuilder(Regex.Replace(value.ToString(), @"\D", ""));
foreach (var i in Enumerable.Range(0, builder.Length / 4).Reverse())
builder.Insert(4*i + 4, " ");
return builder.ToString().Trim();
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Regex.Replace(value.ToString(), @"\D", "");
}
}
Here they are in action:
Huzzah!