WPF Bind to a Method
In this part we will bind to a method. As we type a number into a textbox the results will be displayed in label below it. For this example we use a class which figures out the area of a circle.
Let's start off with a class which calculates the area of a circle. This class has one function named CalculateArea.
Public Class Area
Public Function CalculateArea(ByVal Radius As Double) As Double
Return Math.PI * Radius ^ 2
End Function
End Class
Now that we have a class set up to calculate the area we need 2 additonal classes. The first needs to inherit from ValidationRule to alert the user if they enter an incorrect value (textbox's border turns red for invalid values). The other need to inherit from IValueConveter to convert the user input from string to double and back again.
Imports System.Windows.Controls
Imports System.Windows.Data
Public Class ValidDouble
Inherits ValidationRule
Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As System.Globalization.CultureInfo) As System.Windows.Controls.ValidationResult
Dim num As Double
If Double.TryParse(value.ToString, num) Then
Return New ValidationResult(True, Nothing)
Else
Return New ValidationResult(False, "Invalid Number")
End If
End Function
End Class
Public Class DoubleToString
Implements IValueConverter
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
If value IsNot Nothing Then
Return value.ToString
Else
Return Nothing
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
Dim num As Double
If (value IsNot Nothing) AndAlso Double.TryParse(value.ToString, num) Then
Return num
Else
Return Nothing
End If
End Function
End Class
Now that we have the classes we need its time to register the namespaces with the form.
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFBindToMethod"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="WPFBindToMethod" Height="300" Width="300"
>
Finally we will use an ObjectDataProvider to bind to the method and register the ValidationRule with the form.
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:Area}"
MethodName="CalculateArea" x:Key="CircleArea">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<local:DoubleToString x:Key="doubleToString" />
</Window.Resources>
The Form's complete XAML
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFBindToMethod"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="WPFBindToMethod" Height="300" Width="300"
>
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:Area}"
MethodName="CalculateArea" x:Key="CircleArea">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<local:DoubleToString x:Key="doubleToString" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="140"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right">Radius of the Circle:</Label>
<TextBox Grid.Row="0" Grid.Column="1" Name="tb">
<TextBox.Text>
<Binding Source="{StaticResource CircleArea}" Path="MethodParameters[0]"
BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource doubleToString}">
<Binding.ValidationRules>
<local:ValidDouble/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Label Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right">Area of the Circle:</Label>
<Label Grid.Column="1" Grid.Row="1" Content="{Binding Source={StaticResource CircleArea}}"></Label>
</Grid>
</Window>