Sometimes we have to convert value depends on more than one variables. In that case we are going to use the multi value converter. Lets suppose we want to define the control template of progress bar and instead of displaying its current value, we want to display the current progress in percentage. Here is a class diagram to show the class hierarchy of binding.
Here is our multi value converter to do this.
1: [ValueConversion(typeof(String), typeof(String))]2: public class MyProgressBarConverter : IMultiValueConverter3: {4: public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)5: {6: double value = (double)values[0];7: double min = (double)values[1];8: double max = (double)values[2];9: double range = max - min;10: double currentPosition = value - min;11: double percentage = currentPosition * 100 / range;12: return String.Format("{0}%", percentage.ToString());13: }14:15: public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)16: {17: throw new NotImplementedException();18: }19: }20:This converter accept three parameters in values array. The first one is the current value of progress bar, second one is minimum value of progress bar and third one is maximum value of progress bar. We pass these values in the form of Multi binding. Here is XAML code to define the multi binding.
1: <ControlTemplate x:Key="ProgressTemplate">2: <Grid>3: <Ellipse Fill="{TemplateBinding Background}"4: Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"5: Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>6: <TextBlock Foreground="{TemplateBinding Foreground}"7: FontSize="32" FontWeight="Bold"8: HorizontalAlignment="Center" VerticalAlignment="Center">9: <TextBlock.Text>10: <MultiBinding Converter="{StaticResource MyProgressBarConverterObj}">11: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/>12: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum"/>13: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/>14: </MultiBinding>15: </TextBlock.Text>16: </TextBlock>17: </Grid>18: </ControlTemplate>19:But first we create an object of our converter. Here is a XAML code to create an object of our multi value converter.
1: <local:MyProgressBarConverter x:Key="MyProgressBarConverterObj"/>Now our progress bar will display the current progress in the form of percentage in blue ellipse. Here is complete XAML code of the program.
1: <Window x:Class="WpfProgressBar.Window1"2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"4: xmlns:local="clr-namespace:WpfProgressBar"5: Title="Progress Bar" Height="300" Width="400">6: <Window.Resources>7: <local:MyProgressBarConverter x:Key="MyProgressBarConverterObj"/>8: <ControlTemplate x:Key="ProgressTemplate">9: <Grid>10: <Ellipse Fill="{TemplateBinding Background}"11: Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"12: Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>13: <TextBlock Foreground="{TemplateBinding Foreground}"14: FontSize="32" FontWeight="Bold"15: HorizontalAlignment="Center" VerticalAlignment="Center">16: <TextBlock.Text>17: <MultiBinding Converter="{StaticResource MyProgressBarConverterObj}">18: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/>19: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum"/>20: <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/>21: </MultiBinding>22: </TextBlock.Text>23: </TextBlock>24: </Grid>25: </ControlTemplate>26: </Window.Resources>27:28: <Grid Background="AliceBlue">29: <Grid.RowDefinitions>30: <RowDefinition/>31: <RowDefinition Height="2*"/>32: <RowDefinition Height="2*"/>33: </Grid.RowDefinitions>34:35: <Grid.ColumnDefinitions>36: <ColumnDefinition/>37: <ColumnDefinition/>38: </Grid.ColumnDefinitions>39:40: <TextBlock Grid.Row="0" Grid.Column="0" Margin="5"41: VerticalAlignment="Center" Text="Enter Percentage"/>42: <TextBox Grid.Row="0" Grid.Column="1" Margin="5" Name="txtPercent" VerticalAlignment="Center">43: </TextBox>44: <ProgressBar Margin="5" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"45: Minimum="100" Maximum="500" Value="{Binding ElementName=txtPercent, Path=Text}"/>46: <ProgressBar Margin="5" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"47: Minimum="100" Maximum="500" Foreground="Yellow" Background="Blue"48: Value="{Binding ElementName=txtPercent, Path=Text}"49: Template="{StaticResource ProgressTemplate}">50: </ProgressBar>51: </Grid>52: </Window>53:54:And here is complete C# code of the program.
1: using System;2: using System.Collections.Generic;3: using System.Linq;4: using System.Text;5: using System.Windows;6: using System.Windows.Controls;7: using System.Windows.Data;8: using System.Windows.Documents;9: using System.Windows.Input;10: using System.Windows.Media;11: using System.Windows.Media.Imaging;12: using System.Windows.Navigation;13: using System.Windows.Shapes;14: using System.Globalization;15:16: namespace WpfProgressBar17: {18: /// <summary>19: /// Interaction logic for Window1.xaml20: /// </summary>21: public partial class Window1 : Window22: {23: public Window1()24: {25: InitializeComponent();26: }27: }28:29: [ValueConversion(typeof(String), typeof(String))]30: public class MyProgressBarConverter : IMultiValueConverter31: {32: public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)33: {34: double value = (double)values[0];35: double min = (double)values[1];36: double max = (double)values[2];37: double range = max - min;38: double currentPosition = value - min;39: double percentage = currentPosition * 100 / range;40: return String.Format("{0}%", percentage.ToString());41: }42:43: public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)44: {45: throw new NotImplementedException();46: }47: }48: }49:This is the output of the program.

Well done!
By: Haris Čusto on February 7, 2011
at 10:36 am
Thanks.
By: zamjad on April 12, 2011
at 9:53 am
I’m interested in knowing how I can use a custom MultiValueConverter for adding sub-grouping. For instance, in your State->County->City blog-post (on multi-grouping), it is assumed that the objects contain StateName and CountyName strings, but if instead they are StateIDs and CountyIDs, you’d need to run both the StateId and the CountyId through a multi-value converter (cause you need the StateId-CountyId pair to get the CountyName.
How would you call this, particularly as it relates to multi-grouping?
By: Mark on August 5, 2011
at 7:40 pm
Hi Mark
I have to see that how can i do this. I will post a blog entry once I will find a solution of the problem you posted in your preffered way.
Thanks to read my blog.
By: zamjad on August 11, 2011
at 8:03 am
Is this correct for this converter?
–
[ValueConversion(typeof(String), typeof(String))]
By: Abhsihek on September 9, 2011
at 5:25 am
Thanks for point out this it should be
[ValueConversion(typeof(double), typeof(String))]
By: Zeeshan Amjad on September 12, 2011
at 9:15 pm