A value converter allows you to dynamically convert values during the process of data binding before the bound value is actually used. A value converter at heart, is a custom class that inherits from the IValueConverter
interface. This interface contains two methods—Convert
and ConvertBack—
which we have to implement. Once the value converter is created, we can use it directly in our XAML.
Converters let us define custom logic for the different properties we have in our application. It is not uncommon to see a converter that converts one type of value to a completely different type, for example, a converter that converts a number value to a color value. Another example would be a conversation of text to Boolean values so a checkbox can be checked based on certain words.
Let's go ahead and create our first converter and see with firsthand experience why this feature is so powerful.
Open the Chapter5-Converters project from the downloadable content of this book in Visual Studio 2010. Build and run the application and you should get the result, as shown in the following screenshot:
This application allows you to change the color of the rectangle by using the Choose your color drop-down menu above it. The thing is that if you try to change the color using that drop-down menu now, nothing happens. If you think about it for a minute, you'll realize we now have two completely different types of values, which we are going to work with in order to change the color of the rectangle's fill—the combobox color names (strings) and the actual color for the rectangle fill (SolidColorBrush
). This is where value converters come into play. We are going to use a string value on the Fill
attribute of the rectangle, and by using a value converter, we'll convert it into something the Fill
attribute can understand—SolidColorBrush
.
Under the Classes
folder in the project, create a new class called ColorConverter.cs
.
Change the class declaration so that it will inherit from the IValueConverter
interface and implement the interface. Your class should look as follows:
public class ColorConverter:IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
The interface requires us to implement two methods—Convert
and ConvertBack
. The Convert
method is used when the data is moving from the source to the target; in our example that would be when the Fill
property of the rectangle receives its string binding. ConvertBack
is the exact opposite; it is used when the data moves from the target back to the source. We won't be using the ConvertBack
method in our example, so you can leave it as not implemented. Now it's time to implement the Convert
method. We know we are getting a string as input, and based on that string, we will output a SolidColorBrush
object. Replace the content of the Convert
method with the following code snippet:
string ChosenColor = value!=null ? (value as ComboBoxItem).Content.ToString() : null; switch (ChosenColor) { case "Red": return new SolidColorBrush(Colors.Red); case "Blue": return new SolidColorBrush(Colors.Blue); case "Black": return new SolidColorBrush(Colors.Black); } return null;
Here, there's nothing that we haven't seen before. We first check if the value that we receive from the binding expression is not null. If it isn't, we are casting the value as ComboBoxItem
, because this is the item that we receive from the binding (check the ColorEntity
class, and you'll see that the TheColor
property is defined as ComboBoxItem
type), and then use the ToString
method on its content to get the name of the color the user chose from the drop-down menu.
Once we have the color name, we will use a simple switch/case
statement to return the correct SolidColorBrush
based on the chosen color.
Our converter is now complete, so it's time to use it in our binding expression by using the Converter
object of the Binding
class. In order to be able to use our new converter in XAML, we first have to add it as a resource. We will discuss resources in detail in Chapter 7, Structuring Applications, but for now it's enough to know that a resource is a piece of code or style that you can reference in your XAML. Resources, like styling, which we discussed earlier, can be defined on various levels from element to page. In this case, we are going to add the element to the page level, so open the App.xaml
file and add the namespace for the Classes
folder of our project as local:
xmlns:local="clr-namespace:Chapter5_Converters.Classes"
Next, we need to add the converter itself as a resource. Resources are accessed in XAML by their Key
property, so make sure you use that property when setting your resource. Add the following line of code between the opening and closing of the Application.Resources
elements:
<local:ColorConverter x:Key="ColorConverter"/>
That's it. We can now access our converter in XAML by using its Key
value—ColorConverter
.
Open the MainPage.xaml
file and change the rectangle's Fill
property as follows:
Fill="{Binding TheColor,Converter={StaticResource ColorConverter}}"
The syntax here is as follows; we first tell the Fill
property that it is bound to the TheColor
property. We then use the Converter
object and bind it to the ColorConverter
resource we defined earlier using the StaticResource
keyword. Can you tell the reason why the fill will change every time the drop-down value changes? (Hint: it's got to do with an interface).
Build and run your application, and you will see that every time you change the value of the combobox, the rectangle's fill changes accordingly:
There may be times when you wish to pass parameters to your value converter. Passing parameters is easily done by using the ConverterParameter
object exposed by the Binding
class. Let's assume we want to pass the value of'true'
to the converter in the previous example. All we have to do is change the Fill
property's binding expression as follows:
Fill="{Binding TheColor,Converter={StaticResource ColorConverter},ConverterParameter='true'}"
As parameter is an object you can practically pass on to it just about anything you want. This can be useful if you need to pass more than just a single parameter to your converter. Once set, you can read this parameter back in your converter class using the parameter argument.
While binding is most commonly done in the XAML layer, sometimes you may need to create dynamic binding in code behind. The following code snippet is a representation of the preceding binding expression in the code behind layer of the application:
Binding binding = new Binding("TheColor"); binding.Source = entity; binding.Converter = new ColorConverter(); binding.ConverterParameter = true; rect.SetBinding(Rectangle.FillProperty, binding);
We first initiate a new instance of the Binding
class and pass it the name of the property we are binding to. Next, we set the source of the binding, the converter if needed, a converter parameter. Finally, we use the SetBinding
method on FrameworkElement
we wish to use (in our case, rect
is the rectangle we used so far), and specify the name of the property we wish to bind and the binding instance.
3.149.27.72