I'm trying to use MultiBinding with Xamarin.Forms 4.8, and I can't get it to work. I have this very simple converter:
public class QuantityLabelConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return "Hello World";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And I'm trying to use it in an XAML label, like this:
<Label>
<Label.Text>
<MultiBinding Converter="{StaticResource QuantityLabelConverter}">
<Binding Path="SelectedQuantity" />
<Binding Path="OutstandingQuantity" />
</MultiBinding>
</Label.Text>
</Label>
Now, when I debug, I can see that the converter is called three times: one with two null values, then another one when the SelectedQuantity value is set, and a last time when OutstandingQuantity value is assigned. So the link between the bindings and the converter seems to be working fine.
However, the page crashes and I get a "Value cannot be null.\nParameter name: element" System.ArgumentNullException.
If I replace the previous XAML with a simple
<Label Text="Hello World">
The page shows without problems, so there is something wrong with how the MultiBinding is set, but I don't know what...
You need to return BindableProperty.UnsetValue to use the binding FallbackValue .
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
foreach (var value in values)
{
if (!(value is string b))
{
return "xxx";
// set a default value when unset
}
}
string str1 = values[0].ToString();
string str2 = values[1].ToString();
return str1+str2;
}
##Update
I had tested the sample and found out the cause
If you want to binding the property of ViewModel . You need to implement the interface INotifyPropertyChanged of the property instead of BindableObject .
public class MainViewModel : INotifyPropertyChanged
{
string _name="";
string _surname="";
public string Name
{
get { return _name; }
set
{
if(_name!=value)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
public string Surname
{
get { return _surname; }
set
{
if(_surname!=value)
{
_surname = value;
OnPropertyChanged("Surname");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class NameConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
foreach (var value in values)
{
if (!(value is string b))
{
return " ";
// set a default value when unset
}
}
string str1 = values[0].ToString();
string str2 = values[1].ToString();
return str1 + str2;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}