.NET Tips and Tricks

Blog archive

Massaging Bound Data in WPF and Silverlight

I was recently asked by a WPF programmer how to modify a value passed between bound properties in a XAML file. You can't, for instance, integrate math into a binding expression, as this example does, to divide the value returned by 2:

<Image Height="100" Width="100" Name="MyImage" Source="Me.jpg" 
     Opacity="{Binding ElementName=MySlider, Path=Value/2}" /&rt;
This doesn't work, either:
<Image Height="225" Width="300" Name="CurrentImage" Source="Me.jpg" 
     Opacity="{Binding ElementName=MySlider, Path=Value}/2" /&rt;
While XAML gives you a lot of options when binding a property on one control to something else, modifying the data isn't allowed; at least, not directly. The answer is to use a custom converter. Programmers usually create converters to handle converting the data type of one property to the data type to another property (though XAML will handle a lot of conversions -- numerics to strings, for instance --on its own). But you can also use converters to massage the data in any way you want. This example, for instance, binds the Opacity setting for an Image control to the value in a slider control:
<Slider Margin="10" Name="MySlider" Minimum="0.0" 
     Maximum="2" Value="0.5"/&rt; 
<Image Height="100" Width="100" Name="MyImage" Source="Me.jpg" 
     Opacity="{Binding ElementName=MySlider, Path=Value}" /&rt;

Let's say that you want the transparency to be one-half of the value in the Slider: a converter will solve the problem. This converter, for instance, divides the number passed to it by 2 in its Convert method:

[ValueConversion(typeof(int), typeof(int))]
public class Divider : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, System.Globalization.CultureInfo culture)
    {
        return object/2;
    }
    public object ConvertBack(object value, Type targetType, 
        object parameter, System.Globalization.CultureInfo culture)
    {
        return object * 2;        
    }
}

You need to do three things to use your converter. First, define a namespace for your converter (I've assumed that the converter is in the same project as the XAML file and the namespace for the project is MyApp):

<Window x:Class="MyClass"
  …
  xmlns:current="clr-namespace:MyApp"&rt;

Then you have to add your converter to your resources. I'm adding this converter to the Window's resources with the key MyDivider:

<Window.Resources&rt;
  <current:Divider x:Key="MyDivider"/&rt;
</Window.Resources&rt;

Finally, invoke your converter by passing the resource's key to the StaticResource object's constructor to retrieve it from the resources collection, and then passing that result to the Binding object's Converter property, like this:

<Image Height="100" Width="100" Name="MyImage" Source="Me.jpg" 
       Opacity="{Binding ElementName=MySlider, Path=Value 
               Converter={StaticResource MyDivider}}

Posted by Peter Vogel on 08/09/2012 at 1:16 PM


comments powered by Disqus

Featured

  • Python in VS Code Adds Data Viewer for Debugging

    The January 2021 update to the Python Extension for Visual Studio Code is out with a short list of new features headed by a data viewer used while debugging.

  • GitHub Ships Enterprise Server 3.0 Release Candidate

    It's described as "the biggest ever change to Enterprise Server," with improvements to Actions, Packages, mobile, security and more.

  • Attacks on .NET Apps Grow in Number, Severity, Says Security Firm

    .NET apps were found to have more serious vulnerabilities and suffer more attacks last year, according to data gathered by Contrast Labs.

  • Microsoft Opens Up Old Win32 APIs to C# and Rust, More Languages to Come

    Microsoft is opening up old Win32 APIs long used for 32-bit Windows programming, letting coders use languages of their choice instead of the default C/C++ option.

Upcoming Events