Friday, November 28, 2008

WPF OneWay Binding Part 2

In the last part we bound a label to the value of the scrollbar. In this part we will format the scrollbar's value before we display it.


To be able to format the output of a bound value you need a class which inherits from IValueConverter. For this example I am using the NumbersToWords function found here to convert the number to a word for display.



Public Class NumberToWord
Implements IValueConverter


Private Function NumbersToWords(ByVal num As Decimal) As String
Dim power_value(5) As Decimal
Dim power_name(5) As String
Dim digits As Integer
Dim result As String
Dim i As Integer

' Initialize the power names and values.
power_name(1) = "trillion" : power_value(1) = 1000000000000.0#
power_name(2) = "billion" : power_value(2) = 1000000000
power_name(3) = "million" : power_value(3) = 1000000
power_name(4) = "thousand" : power_value(4) = 1000
power_name(5) = "" : power_value(5) = 1
For i = 1 To 5
' See if we have digits in this range.
If num >= power_value(i) Then
' Get the digits.
digits = Int(num / power_value(i))
' Add the digits to the result.
If Len(result) > 0 Then result = result & ", "
result = result & Words_1_999(digits) & " " & power_name(i)
' Get the number without these digits.
num = num - digits * power_value(i)
End If
Next i
NumbersToWords = Trim$(result)
End Function

' Return words for this value between 1 and 999.
Private Function Words_1_999(ByVal num As Integer) As String
Dim hundreds As Integer
Dim remainder As Integer
Dim result As String
hundreds = num \ 100
remainder = num - hundreds * 100
If hundreds > 0 Then
result = Words_1_19(hundreds) & " hundred "
End If
If remainder > 0 Then
result = result & Words_1_99(remainder)
End If
Words_1_999 = Trim$(result)
End Function

' Return a word for this value between 1 and 19.
Private Function Words_1_19(ByVal num As Integer) As String
Select Case num
Case 1
Words_1_19 = "one"
Case 2
Words_1_19 = "two"
Case 3
Words_1_19 = "three"
Case 4
Words_1_19 = "four"
Case 5
Words_1_19 = "five"
Case 6
Words_1_19 = "six"
Case 7
Words_1_19 = "seven"
Case 8
Words_1_19 = "eight"
Case 9
Words_1_19 = "nine"
Case 10
Words_1_19 = "ten"
Case 11
Words_1_19 = "eleven"
Case 12
Words_1_19 = "twelve"
Case 13
Words_1_19 = "thirteen"
Case 14
Words_1_19 = "fourteen"
Case 15
Words_1_19 = "fifteen"
Case 16
Words_1_19 = "sixteen"
Case 17
Words_1_19 = "seventeen"
Case 18
Words_1_19 = "eightteen"
Case 19
Words_1_19 = "nineteen"
Case Else
Words_1_19 = ""
End Select
End Function

' Return a word for this value between 1 and 99.
Private Function Words_1_99(ByVal num As Integer) As String
Dim result As String
Dim tens As Integer
tens = num \ 10
If tens <= 1 Then ' 1 <= num <= 19
result = result & " " & Words_1_19(num)
Else
' 20 <= num
' Get the tens digit word.
Select Case tens
Case 2
result = "twenty"
Case 3
result = "thirty"
Case 4
result = "forty"
Case 5
result = "fifty"
Case 6
result = "sixty"
Case 7
result = "seventy"
Case 8
result = "eighty"
Case 9
result = "ninety"
End Select
' Add the ones digit number.
result = result & " " & Words_1_19(num - tens * 10)
End If
Words_1_99 = Trim$(result)
End Function

Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
Dim d As Double
If Double.TryParse(value.ToString, d) Then
Return NumbersToWords(CDec(d))
Else
Return value
End If
End Function

Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Return Nothing
End Function
End Class

Now that we created the class we need to register the xml namespace with the window. The namespace you need to use for this is clr-namespace:NamespaceName. In this case it is the applications name. I am adding the local prefix so we can reference it later.


xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFOneWayBind"
Title="WPFOneWayBind" Height="300" Width="300"
>

Now we need to make the converter a resource for the window.







Right after we set the path for the binding we can specify the converter. The converter is a StaticResource of the window.


No comments: