Dan
Dan

Reputation: 468

Binding a list of string to a Xamarin Xaml with a converter

I have a list of enum called TransportModeType binded to a Listview with a converter in the datatemplate. The ViewModel looks like this

public class TransportTypeViewMode:ViewModelBase{
public TransportTypeViewMode()
{
    TransportTypes= new List<TransportTypeEnum>();
    TransportTypes.add(TransportTypeEnum.Car);
    TransportTypes.add(TransportTypeEnum.Bus);
    TransportTypes.add(TransportTypeEnum.Plane);
}

List<TransportTypeEnum> TransportTypes{get;set;}}

The ListView looks like this

  <ListView ItemsSource="{Binding TransportModeTypes}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ContentView>
                                <Image Source="{Binding Converter={StaticResource ListToImageConverter}}" Aspect="AspectFit"/>
                            </ContentView>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

and my converter called ListToImageConverter looks like this

public class TransportModeEnumToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var transporttModeType = (TransportModeTypeEnum) value;
        string imagePath = String.Empty;    

        switch (transporttModeType)
        {
            case TransportModeTypeEnum.Bus:
                imagePath = "bus.png";
                break;
            case TransportModeTypeEnum.Train:
                imagePath = "train.png";
                break;
            case TransportModeTypeEnum.Car:
                imagePath = "car.png";
                break;
            case TransportModeTypeEnum.Plane:
                imagePath = "plane.png";
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }


        imagePath = "Common.Images." + imagePath;
        var imgResc= ImageSource.FromResource(imagePath);
        return imgResc;
    }


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

the converter throws an exception that the Value is null.. what am i missing in my binding

Upvotes: 1

Views: 2602

Answers (2)

JoeTomks
JoeTomks

Reputation: 3276

EDIT:

you firstly need to convert your enums to strings, as enums are not a valid itemsource for a listview. So you would need to use the converter for this too.

ViewModel:

public class TransportTypeViewMode : ViewModelBase
{
    public TransportTypeViewMode()
    {
        TransportTypes= new List<TransportTypeEnum>();
        TransportTypes.add(TransportTypeEnum.Car);
        TransportTypes.add(TransportTypeEnum.Bus);
        TransportTypes.add(TransportTypeEnum.Plane);
    }      

    Public List<TransportTypeEnum> TransportTypes{get;set;}}
}

Your enum to string converter:

public class TransportModeEnumToString : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var transporttModeType = (TransportModeTypeEnum) value;
        string transportName = String.Empty;    

        switch (transporttModeType)
        {
            case TransportModeTypeEnum.Bus:
                transportName = "bus";
                break;
            case TransportModeTypeEnum.Train:
                transportName = "train";
                break;
            case TransportModeTypeEnum.Car:
                transportName = "car";
                break;
            case TransportModeTypeEnum.Plane:
                transportName = "plane";
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
        return transportName;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Your string to imagesource conveter:

public class StringToImagesourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string transporttModeType = (string)value;
        string imagePath = String.Empty;    

        switch (transporttModeType)
        {
            case "bus":
                break;
            case TransportModeTypeEnum.Train:
                imagePath = "train.png";
                break;
            case "car":
                imagePath = "car.png";
                break;
            case "plane":
                imagePath = "plane.png";
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }

        imagePath = "Common.Images." + imagePath;
        var imgResc= ImageSource.FromResource(imagePath);
        return imgResc;
    }
}

and your xaml should be something like:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:c="location of your converter classes"
             >
<ContentPage.Resources>
  <c:EnumToStringConverter x:Key="enumtostring" />
  <c:StringToImagesourceConverter x:Key="stringtoimagesource" />
</ContentPage.Resources>
<ContentPage.Content>
    <ListView ItemsSource="{Binding TransportModeTypes Converter={StaticResource EnumToStringConverter}}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ContentView>
                            <Image Source="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource StringToImagesourceConverter}}" Aspect="AspectFit"/>
                        </ContentView>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
    </ListView>
</ContentPage.Content>

Upvotes: 2

Gerald Versluis
Gerald Versluis

Reputation: 34013

Just add a null check and return an empty string or something appropriate.

When the binding is done it gets initialized sometimes with a null value. You can probably safely ignore it. So edit you code something like this:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
        if (value == null)
          return String.Empty;

        var transporttModeType = (TransportModeTypeEnum) value;
        string imagePath = String.Empty;   
...

In addition, Jason remarked in the comments that you seem to be missing the path you are binding to here:

<Image Source="{Binding YourProperty, Converter={StaticResource ListToImageConverter}}" Aspect="AspectFit"/>

Notice how I added YourProperty, which seemed to be missing. Of course, replace it by the name of an actual property in your object.

Upvotes: 0

Related Questions