You can look up the ICustomFormatter interface at Microsoft and get a very complete example that includes code designed to make it bulletproof in an complex environment. Unfortunately, that also makes it more difficult to understand. My goal is to make this a lot easier for you to use in a less complex case that is probably more typical of real world requirements you will have.
To illustrate this less complex custom formatting, I'm going to code a program that will create a custom formatter that randomly substitutes an "@" for the letter "o" in a string of text. In pseudocode, something like this:
FormattedText = String.Format( CustomFormatProvider, FormatSpecifier, InputText)
Recall that the usual Format method of the String object uses this syntax:
String is the format specifier and Object is the text or number to be formatted. But another overload of Format looks like this:
String.Format(IFormatProvider, String, Object())
When this signature is present, you can write your own code to do just about anything. Step one is to code a custom format provider. But it's not quite as simple as coding a subroutine. To narrow in on that, first check out the Microsoft documentation to find out what we're working with:
Click Here to display the illustration
The real information you need is circled in the illustration:
GetFormat Returns an object that provides formatting services for the specified type.
An object is an instance of a class. If you code a class that contains a GetFormat method and also has a Format method that provides formatting services (that is, it modifies whatever is passed to it the way you want it), then you have implemented the interface.
Suppose we call our custom formatting provider "AtSignFormatter". Here's a class that does most of what we want:
Public Class AtSignFormatter : Implements IFormatProvider, ICustomFormatter ' Changes random "o" characters to "@" characters Public Function GetFormat( ByVal formatType As Type ) As Object _ Implements IFormatProvider.GetFormat Return Me End Function Public Function Format( ByVal fmt As String, ByVal arg As Object, ByVal formatProvider As IFormatProvider ) As String _ ... <code to do the formatting> End Function End Class
The GetFormat function might look a little strange since it just returns the same instance of the class that was called. If you check out Microsoft's code, you'll see more code that checks to see if this really is a custom formatter. It's a good idea to include it, but I coded it this way to boil it down to the essential idea and make it easier to understand.
The other function, named Format, is called in place of the Format that is in Microsoft's code. Here's the complete code of that function:
Public Function Format( ByVal fmt As String, ByVal arg As Object, ByVal formatProvider As IFormatProvider ) As String _ Implements ICustomFormatter.Format Dim theAtSign As Char = Chr(64) ' @ sign Dim strArg As String = CStr(arg) Randomize() For i As Integer = 0 To Len(CStr(arg)) - 1 If CStr(arg).Substring(i, 1) = "o" Then If Rnd() > 0.5 Then strArg = strArg.Remove(i, 1) strArg = strArg.Insert(i, theAtSign) End If End If Next Return strArg End Function
Notice that this code implements a different interface, ICustomFormatter.Format. Again, Microsoft's example code is more complex and more complete while mine is just enough to work correctly in this case. A lot can go wrong and most of the code you will see at Microsoft is designed to make sure it doesn't. That's always a good idea, but I thought that you ought to just see the core of the process first.
The information passed to the Format function helps to complete the picture of just what is happening:
Click Here to display the illustration
Custom formatting is also used very frequently when data is bound with a data source such as a database. On the next page, we show how that works.