Ask Learn
Preview
Please sign in to use this experience.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Today just a quick Tip on a frequently asked question:
How to Bind a parameter within a Converter (Which implements IValueConverter) ? And by the way, can we do this binding on the ConverterParameter property ?
To illustrate this example, here is my scenario :
I need, in my converter, to know 2 things :
Those two integer will help me to calculate the width of a rectangle representing the percentage of the current item distance.
I create and declared a DistanceConverter directly in the page ressources :
<conv:DistanceConverter x:Key="DistanceConverter" />
And I use it in my ItemTemplate:
<Rectangle HorizontalAlignment="Left" VerticalAlignment="Center"
Fill="#00FF84" Margin="10,0" Height="10"
Width="{Binding Path=CurrentItem.Distance,
Converter={StaticResource DistanceConverter},
ConverterParameter={Binding User.TotalDistance},
Mode=TwoWay}">
</Rectangle>
The code of the DistanceConverter is trivial, and you ll get it in the sample provided with this post.
Be aware of the ConverterParameter : I tried to pass a value to the Converter using the ConverterParameter. Not a static value but the bindable value from my User instance.
But during the first execution, my parameter object is null:
So, as you can see, you can’t bind a value directly on the ConverterParameter
The reason why is that the ConverterParameter IS NOT a depency property but a “simple” object. In this situation you can’t use Bindings.
This side effect is true with all XAML plateforms : WP7-8, Silverlight, WPF and of course WinRT.
The idea is to create a dependency property on my converter and not using the ConverterParameter : To be able to create a DP, your converter must inherits from DependencyObject :
public class DistanceConverter : DependencyObject, IValueConverter
{
public UserViewModel CurrentUser
{
get { return (UserViewModel) GetValue(CurrentUserProperty); }
set { SetValue(CurrentUserProperty, value); }
}
public static readonly DependencyProperty CurrentUserProperty =
DependencyProperty.Register("CurrentUser",
typeof (UserViewModel),
typeof (DistanceConverter),
new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Then, I declare my Converter in my page ressources :
<common:LayoutAwarePage.Resources>
<conv:DistanceConverter x:Key="DistanceConverter"
CurrentUser="{Binding User}"
CurrentItem="{Binding CurrentItem}"
MaxWidthAvailable="450" />
</common:LayoutAwarePage.Resources>
And finally, I set my converter in my item Template :
<Rectangle HorizontalAlignment="Left" VerticalAlignment="Center"
Fill="#00FF84" Margin="10,0" Height="10"
Width="{Binding Path=CurrentItem.Distance,
Converter={StaticResource DistanceConverter}}">
</Rectangle>
Here is a screenshot of the property during the binding process:
If you work with a “bindable converter”, remember this : Don’t create your converter directly in your ItemTemplate, like this :
<Rectangle HorizontalAlignment="Left" VerticalAlignment="Center"
Fill="#00FF84" Margin="10,0" Height="10">
<Rectangle.Width>
<Binding Path="CurrentItem.Distance">
<Binding.Converter>
<conv:DistanceConverter
CurrentUser="{Binding User}"
CurrentItem="{Binding CurrentItem}"
MaxWidthAvailable="450" />
</Binding.Converter>
</Binding>
</Rectangle.Width>
</Rectangle>
The binding on each instance of your converter will be too late, and the Convert method will be called BEFORE setting the value in your dependency property :
Other point of interest, If you need an other information from your current item, don’t try to get the current Item with the RelativeSource source like this:
<conv:DistanceConverter x:Key="DistanceConverter"
CurrentUser="{Binding User}"
CurrentItem="{Binding RelativeSource={RelativeSource TemplatedParent}}"
MaxWidthAvailable="450" />
Because your converter is declared in the page ressources, RelativeSource on TemplatedParent doesn’t work
Happy Converters !
Anonymous
March 17, 2013
Hi Sebastien,
if you add your converter to the resources of your itemtemplate/datatemplate the binding will be set before calling the Convert method.
Anonymous
March 18, 2013
If you add your converter directly in your ItemTemplate, it won't be a static Converter, so the object will be instantiate after bindings occurs.
That's why i have declared it in the Page Ressources (it will be a static ressource in this particular case)
Anonymous
April 27, 2014
Hi Sebastian,
I have followed the above and bound my value converter to a value in the viewModel. It gets the first initial value when the page is first called, so I at least know its hooked up correctly. But when I change the bound object and raisePropertyChanged manually it does not re-fire the converter in which the binding is held.
Any ideas?
Anonymous
November 17, 2014
How can we use it with itemtemplate/datatemplate . DependencyProperty always give 0 in this case?
Anonymous
May 11, 2015
Thanks so much, it helped me out! :-)
Anonymous
February 09, 2016
Thanks you so much, you made my job easy :)
Please sign in to use this experience.
Sign in