Click here to Skip to main content
15,902,876 members
Articles / Desktop Programming / WPF

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

Rate me:
Please Sign up or sign in to vote.
3.75/5 (4 votes)
7 Nov 2020Public Domain4 min read 7.7K   114   2   2
Updating user interface in WPF with simple one-way binding
Updating the user interface, while focusing on variables calculations and dealing with user input validation, can be easily left behind. We will see how to automatically refresh the UI, leaving to WPF the burden of doing it.

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:

XML
<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 TextblockOutput” to the TextboxInput”. Close it for now and let’s dig into the code.

First thing, declare a public Property and its private representation.

VB.NET
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.

VB.NET
Public Event PropertyChanged As PropertyChangedEventHandler

The event associated with Input.Textchanged will look like this:

VB.NET
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:

VB.NET
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.

VB.NET
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:

VB.NET
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 TextBlockOutput”:

HTML
<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

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionYou can do better Pin
Издислав Издиславов7-Nov-20 22:05
Издислав Издиславов7-Nov-20 22:05 
I would not rate the article, but I would make few suggestions. The presented example is working, but it seems to me a little bit oversimplified. There is no need to force partial definition of MainWindow class in code-behind to implement INotifyPropertyChanged, although you can do it. Far better approach is to create a base class which do only that and serve as a base view model, and you can set dynamically the data context of every window in an application.

I believe you have background in C++ or in web development, the way you make your code snippets, few lines there, few lines here, and I wonder why you develop using WPF, a framework which is not so recent. WPF was made before the boom in web development and one of the ideas behind it was to be used in heavy LoB applications. To make the story short, a far better approach would be to create a window with more textboxes and a button or combo, values in all textboxes depending on others, and display a validation approach for all of them.

The button should be enabled only when certain valid entries are entered in text boxes. All of this should be achieved in your view model, without the code behind. So you have to use the ICommand interface and make a simple command implementation. The CanExecute method, used by the command, would be called on every change in properties, bind to text boxes. This way the button will be automatically enabled or disabled.
The validation you make in property set accessor is fine for one property, but not for many. If we have two text boxes, A and B, and form is valid only when A AND B have certain values, then you should validate both values on every change. So in such case you can just make a call to validation method on every property setter.
You can implement a validation interface, validation rules, use a validation Error Template for every text box, but I would suggest not to do so, but instead do everything by yourself. Those approaches do more harm than good, and at the end a developer do not really need them. On every change somewhere in text box (or other) you will have the changed values in your model. That's all that is needed. You can then change the template for a specific text box and display custom validation somewhere - not only a some text label around the text box, but why not some symbol like * or ! in text box itself.
AnswerRe: You can do better Pin
Padanian8-Nov-20 0:31
Padanian8-Nov-20 0:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.