Guide to "WPF" and "XAML" Data Binding in Visual Basic .NET

106 15
< Continued from page 1

One thing to learn from this first XAML example of binding is that the relationship is dynamic. In other words, every character that you type into the TextBox is reflected in the Label as soon as you type it. This is very important in something like a Slider control where a change must be sent immediately to the target. The next example binding the Slider control also makes this point.

The Slider is a very useful control that you can use to give the user dynamic control over things like the shape and size of things on the screen or the position in a datastore.


In this next example, we're going to vary the displayed width of an image dynamically using the Slider. The finished result (with an Image Width sized at about 50% with the Slider) looks like this:

--------
Click Here to display the illustration
Click the Back button on your browser to return
--------


I think of a slider as being a "0% to 100%" kind of control and then I multiply that percentage by some base value. Using that thinking, the first try might look something like this:

(Note: This code doesn't work - Illustration only.)

<image name="Image1" stretch="Fill"
   source="Images\visualbasic.jpg"
   width="{Binding ElementName=Slider1, Path=Value*250}"/>
<slider height="22" margin="12,0,10,0"
   x:name="Slider1"
   verticalalignment="Bottom"/>


This doesn't work because you can't embed any kind of calculation into the XAML. It's not a programming language; it's a descriptive language. To make XAML do something like this, you have to use program code that implements the IValueConverter interface.

This interface lets you insert any kind of programming you need to use between the source and the destination of a binding. In this particular case, the source is the Value property of the Slider control and the destination is the Width attribute of the Image control. (In this example, you can also do the whole thing in XAML as well. That solution is shown at the end of the article.)

To get started, first add a Class to the project. I named mine ConvertWidth. When you code ...

Public Class ConvertWidth
   Implements IValueConverter


Intellisense enters the required interface members - Public Function Convert and Public Function ConvertBack - and their parameters automatically. All you have to do is add the code. Convert intercepts the source of the binding and passes it to the code and ConvertBack intercepts target if it's changed. This example only uses Convert. ConvertBack is very useful if, for example, you want to update a database with a value that is changed by the user.

The four parameters that you have to work with are:
  • ByVal value As Object
  • ByVal targetType As System.Type
  • ByVal parameter As Object
  • ByVal culture As System.Globalization.CultureInfo

Value is the source of the binding. That is, the value of the Slider control. In this example, I use parameter to pass the maximum number of pixels that I want to use for a width. Note that they're both specified as Object. In this case, Microsoft programmers have reverted to the old VB6 "it can be anything" design because you can't predict the type that either will be.

Then the code is simply ...

Return CDbl(value) * CDbl(parameter)

... in the Convert Function.

The XAML part of this is considerably more complex.

The converter class is a "resource" to the XAML, so you have to be able to identify it that way. In VB.NET (It's different in C#) we identify it as a local resource with a local namespace. In the Framework 3.5 version of WPF, the way to do this is to make certain you pick the namespace from a list presented by Intellisense. It's very difficult to get it right if you don't. Enter "xmlns:local=" and Intellisense should present you with a list available in your project. In this project, the namespace is:

xmlns:local="clr-namespace:WpfApplication1"

The next step is to make this resource available to the XAML:

<window.resources>
   <local:convertwidth
    x:Key="convertWidth" />
</window.resources>


Notice that local refers to the Class and Key refers (just as it was before) to the Binding in the XAML. Notice the naming convention. This isn't required but most programmers are doing it this way. You could also restrict this resource to a lower level, for example, Grid.Resources in this case.

If you've done all this correctly, you will notice that VB.NET still shows an error in your code because the reference to the Class can't be found. Before you go any further, you still have to Build the project so VB.NET can find that Class in a compiled assembly.

Hopefully, this will all work more smoothly in the next version.

But we're still not finished.

Finally, you have to add this binding to the XAML of the target. Here's what worked for me:

Width="{Binding ElementName=Slider1,
   Path=Value,
   Converter={StaticResource convertWidth},
   ConverterParameter='250'}"


In words, the Converter markup extension points to a resource using a Key value. The resource identifies a Class. The Binding passes parameters to the Class and assigns the returned value to the XAML attribute.

This example is deliberately simple to help coders who are new to the syntax get it right. You can find more complex examples - involving two way conversions, type conversions, and globalization - at Microsoft and other sites. There are a lot of cases where you simply have to use program code to convert values in a binding from one thing to something else. But in this case, it's also useful to note that you really don't have to. If you specify the Maximum value of the Slider as the maximum width of the Image, you can simply code it the same way any two controls can be bound:

<image name="Image1" stretch="Fill"
   Source="Images\visualbasic.jpg"
   Width="{Binding ElementName=Slider1, Path=Value}"
   />
<slider height="22" margin="12,0,10,0"
   x:Name="Slider1"
   VerticalAlignment="Bottom"
   Maximum="250"
   />

Subscribe to our newsletter
Sign up here to get the latest news, updates and special offers delivered directly to your inbox.
You can unsubscribe at any time

Leave A Reply

Your email address will not be published.