Simple WPF Binding in Code-behind for Visual Basic .NET






3.75/5 (4 votes)
Updating user interface in WPF with simple one-way binding
Introduction
The UI management can be time consuming and a source of frustration, especially when our project is made up of several concurrent threads, each of which needs to update its own part of it.
At times, when data flows rapidly in and out of the project, the user needs to have a quick update of important variables. Whether they would be volatile stock market prices or water flow rate in a pipe, the faster the UI update of that property, the faster the reaction of the user to it.
When the same property is accessed from different parts of the project, updating the UI in real time becomes tedious and source of errors. We will see in this small project how to bind the property value to its representation on the UI.
There are multiple better and more in-depth examples on the Internet, although most of them deal with C#, and others are too convoluted to follow. The approach in this project is focused on simplicity and essentiality, for the benefit of inexperienced VB.NET developers.
Setting It Up
The purpose of this project is to validate the user input, parse whether the input is a Double
, and if so, show it with two decimals, thousands separator and the currency symbol. If the user input is not a Double
, visualise an error message. We want this to happen as the user types, and do not want to wait for him to enter or confirm the input.
Step by Step Walkthrough
We’ll start setting up by creating a new WPF .NET Framework, VB.NET project. In the default window, drag just one Textbox
and one Textblock
.
MainWindow.xaml would look more or less like this:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="MainWindow" Height="160" Width="380" ResizeMode="NoResize" >
<Grid x:Name="myGrid" >
<TextBlock x:Name="Output" HorizontalAlignment="Left" Margin="195,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="124" Height="23"/>
<TextBox x:Name="Input" Text="0" HorizontalAlignment="Left" Height="23" Margin="40,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>
We’ll come back to MainWindow.xaml later, when we will need to declare the Binding of the Textblock
“Output
” to the Textbox
“Input
”. Close it for now and let’s dig into the code.
First thing, declare a public Property
and its private
representation.
Private m_InputText As String
Public Property InputText As String
We also need to declare a PropertyChanged
event, that will fire when the property is changed. If multiple properties are present in the project, the same event can be reused, by passing the appropriate argument.
Public Event PropertyChanged As PropertyChangedEventHandler
The event associated with Input.Textchanged
will look like this:
Private Sub Input_TextChanged(sender As Object, e As TextChangedEventArgs) _
Handles Input.TextChanged
InputText = Input.Text
End Sub
What we’re doing with that is just assign the string Input.Text
to the Property InputText
(which is also a String
of course).
It’s time to modify the Property
with our parsing and validation code, like this:
Public Property InputText As String
Get
Return m_InputText
End Get
Set(value As String)
Dim validResult As Double
If Double.TryParse(value, validResult) Then
m_InputText = validResult.ToString("C2")
Else
m_InputText = "Invalid amount"
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("InputText"))
End Set
End Property
Basically, what we are doing is trying to cast the String
to a Double
. If we succeed, the new value will be converted back to a String
, formatted as a two-digit decimal currency value (“C2
”) and assigned to m_InputText
. If no casting is possible, the string
will contain “Invalid Amount
”.
Whether m_InputText
contains a valid currency value or not, we raise a PropertyChanged
event, by passing the appropriate Sender
and Property
that changed. As you see, by changing the PropertyChangedEventArgs
appropriately, the same Event
can be reused for different Properties.
We are already almost there. There are just a couple of more things to do for setting up the Binding.
The UI must be notified that a Property
changed in the code behind, and we also need to tell the Binding what is the DataContext
where to look for the Property
that changed. Notifications are managed by the Interface INotifyPropertyChanged
which resides in the Namespace System.ComponentModel
. We need to import that Namespace, and declare the interface implementation. The binding DataContext
, in our example, is the entire Instance of MainWindow
(Me
). There may times where we need to restrict the DataContext
(e.g.: same property in different instances of a class), but this is beyond the scope of this article.
Imports System.ComponentModel
Class MainWindow
Implements INotifyPropertyChanged
Public Sub New()
InitializeComponent()
DataContext = Me
End Sub
…
The event PropertyChanged
must implement the interface to the UI, therefore its declaration becomes as follows:
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Finally, it’s time to go back and edit the MainWindow.xaml to declare the Binding to our property, by modifying the declaration of TextBlock
“Output
”:
<TextBlock x:Name="Output" HorizontalAlignment="Left" Margin="195,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="124" Height="23" Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}" />
Run the program and you should see the following results.
Valid input:
Invalid input:
Conclusion and Points of Interest
In this article, we just scratched the very surface of the Binding world. By following the example provided, the user could later expand to a whole range of different and more complete implementations and possibilities. Bindings are a simpler way to update the UI, by avoiding the necessity of thread-safe calls and delegates.
The user is encouraged to experiment the two-way Binding, which is not discussed here.
It is also interesting to notice how simple and compact it is to code Binding in VB.NET, when compared to C#.
History
- 6th November, 2020: Initial version