As-you-type formatting adds phone-number grouping while the user enters digits.
dotnet add package RecursiveAI.OneContactRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneContact; using RecursiveAI.OneContact.Phones; var formatter = new AsYouTypeFormatter( Region.Parse("US")); foreach (char digit in "2025550100") Console.WriteLine( formatter.InputDigit(digit));
2 20 202 202-5 202-55 202-555 202-5550 (202) 555-01 (202) 555-010 (202) 555-0100
The formatter never validates; a character other than a digit or initial plus sign stops formatting until Clear() is called.
Unzip the example, then dotnet run.
Variations
Remember a digit’s display position, then reset the formatter:
using RecursiveAI.OneContact; using RecursiveAI.OneContact.Phones; var formatter = new AsYouTypeFormatter( Region.Parse("US")); formatter.InputDigitAndRememberPosition( '2'); string display = ""; foreach (char digit in "025550100") display = formatter.InputDigit(digit); Console.WriteLine(display); Console.WriteLine( formatter.RememberedPosition); formatter.Clear(); Console.WriteLine( formatter.InputDigit('4'));
(202) 555-0100 2 4
Related recipes
The short answer
Create an AsYouTypeFormatter for the input’s default region and pass each new character to InputDigit. Show the returned string in the field. One formatter follows one number being typed; create separate instances for separate fields. The example prints each intermediate display value, ending at (202) 555-0100.
This API formats incomplete input. It is not the API for storing a completed phone number, and it does not validate one. The phone documentation explicitly says that it never validates. A nicely grouped field must not become a “verified phone” badge.
How to format phone number in C#?
For an interactive field, use the incremental formatter rather than a fixed numeric format string. At first there are too few digits to choose a grouping pattern. The first two keys echo; from the third, the formatter tries prefixes and the region’s candidate patterns. Further digits narrow those candidates, so the displayed grouping can change as the input grows.
For a completed number, parse and format the completed value instead. The related recipe covers that separate task. Do not feed an already formatted display back into the same incremental formatter: spaces and punctuation are input characters too, and they switch it to literal-input behavior. Keep the unformatted editing input distinct from the display text.
How do I format a phone number as the user types in C#?
The snippet at the top loops over characters to simulate key presses. In a UI, call the same method once for each appended character and assign its return value to the visible text. Protect the field update from recursively treating the replacement display text as another user edit. The console example deliberately has no UI-framework dependency.
Use InputDigitAndRememberPosition for a digit whose position you need after grouping changes. RememberedPosition is the index in the latest output just after that digit. The variation remembers the first digit and prints position 2, because the final display starts with an opening parenthesis. It is not an index in the original raw string.
For deletion, replacement, or a paste into the middle, a simple integration can call Clear() and replay the revised raw input. There is no deletion method in this formatter. Remember the relevant digit again while replaying if the UI needs to restore a caret. The UI still decides which raw digit corresponds to the user’s selection.
How do I format an international phone number in C#?
An initial plus sign or the region’s international prefix switches the formatter toward international formats. Once the calling code is read, it uses the region that owns that code. The default region is still important for national input, which has no explicit country calling code.
Digits from any script count. A plus sign counts only in the first position; other characters stop automatic formatting, and subsequent output is the text exactly as typed until reset. This behavior preserves odd input rather than throwing, but it also means an input mask that inserts its own punctuation can defeat the formatter. Let one layer own display grouping, and validate the completed value separately.