How does one use a converter with Multiple parameters in a Windows Phone 7 Application?
Converters always implement IValueConverter. That means a call to Convert or ConvertBack passes a single additional parameter. That parameter is extracted from the XAML.
As Hitesh Patel suggests there is nothing to stop you putting more than one value into the parameter, so long as you have a delimiter to separate them out later, but you cannot use a comma as that delimits the XAML!
e.g.
<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
Converter={StaticResource MyConverter},
ConverterParameter=Param1|Param2}" />
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
string parameterString = parameter as string;
if (!string.IsNullOrEmpty(parameterString))
{
string[] parameters = parameterString.Split(new char[]{'|'});
// Now do something with the parameters
}
}
Note, I have not checked it to see if a Pipe "|" character is valid in XAML there (should be), but if not just choose another character that does not clash.
Later versions of .Net do not require a character array for the simplest version of Split
, so you can use this instead:
string[] parameters = parameterString.Split('|');
A trick eBay used to use in urls, years ago, was to delimit data in the URL with QQ. A double-Q does not naturally occur in text data. If you ever get stuck for a text delimiter that will avoid encoding issues just use QQ... This will not work with split though (which requires single characters, but nice to know) :)
While the above answers may be feasible, they seem to be overly complicated. Simply use an IMultiValueConverter
with an appropriate MultiBinding
in the XAML code. Assuming that your ViewModel has the properties FirstValue
, SecondValue
, and ThirdValue
, which are an int
, a double
, and a string
, respectively, a valid multi converter might look like this:
public class MyMultiValueConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
int firstValue = (int)values[0];
double secondValue = (double)values[1];
string thirdValue = (string)values[2];
return "You said " + thirdValue + ", but it's rather " + firstValue * secondValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException("Going back to what you had isn't supported.");
}
}
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myNs:MyMultiValueConverter}">
<Binding Path="FirstValue" />
<Binding Path="SecondValue" />
<Binding Path="ThirdValue" />
</MultiBinding>
</TextBlock.Text>
Since it requires neither fumbling with the ProvideValue
method required by MarkupExtension
, nor the specification of a DependencyObject
inside(!) a converter, I do believe that this is the most elegant solution.
You can always derive from DependecyObject
class and add as many DependencyProperty
objects as you want. For example:
ExampleConverter.cs
public class ExampleConverter : DependencyObject, IValueConverter
{
public string Example
{
get => GetValue(ExampleProperty).ToString();
set => SetValue(ExampleProperty, value);
}
public static readonly DependencyProperty ExampleProperty =
DependencyProperty.Register("Example", typeof(string), typeof(ExampleConverter), new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//Do the convert
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And then in XAML:
ExampleView.xaml
<ResourceDictionary>
<converters:ExampleConverter x:Key="ExampleConverter" Example="{Binding YourSecondParam}"/>
</ResourceDictionary>
...
<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
Converter={StaticResource ExampleConverter},
ConverterParameter={Binding YourFirstParam}}" />
This can be done using System.Windows.Markup.MarkupExtension
(docs).
This will allow you pass values to the converter which could be used as arguments or return values, for example:
public class CustomNullToVisibilityConverter : MarkupExtension, IValueConverter
{
public object NullValue { get; set; }
public object NotNullValue { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return NullValue;
return NotNullValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Usage:
...
Visibility="{Binding Property,
Converter={cnv:CustomNullToVisibilityConverter NotNullValue=Visible, NullValue=Collapsed}}"
/>
...
Be sure to reference the namespace of the converter in the .xaml
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With