Xamarin形式的MultiBinding:元素为null

问题描述

我正在尝试将MultiBinding与Xamarin.Forms 4.8一起使用,但无法使其正常工作。我有一个非常简单的转换器:

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,CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我正试图在XAML标签中使用它,像这样:

<Label>
    <Label.Text>
        <MultiBinding Converter="{StaticResource QuantityLabelConverter}">
            <Binding Path="SelectedQuantity" />
            <Binding Path="OutstandingQuantity" />
        </MultiBinding>
    </Label.Text>
</Label>

现在,当我进行调试时,我可以看到该转换器被调用了三次:一次具有两个空值,然后一次是在设置SelectedQuantity值时一次,而最后一次是在分配OutstandingQuantity值时。因此,绑定和转换器之间的链接似乎工作正常。

但是,页面崩溃了,我得到一个“值不能为空。\ n参数名称:element” System.ArgumentNullException。

如果我用简单的替换以前的XAML

<Label Text="Hello World">

页面显示没有问题,因此MultiBinding的设置存在问题,但是我不知道...

解决方法

您需要返回 BindableProperty.UnsetValue 才能使用绑定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

我已经测试了样品并找到了原因

如果要绑定ViewModel的属性。您需要实现属性的接口 INotifyPropertyChanged 而不是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,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,CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

enter image description here