0

I need to add pictures to dropdown items.
In the dropdown I need to see the icon first and the text below. But for some reason, I can't see images, though I see the empty place instead.

My project is Xamarin.Android with MVVMCross. I'm missing something, maybe I need some plugins?

I have MypageView.axml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include
        layout="@layout/toolbar" />
    <TextView
        android:id="@+id/city"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textSize="12sp"
        android:layout_below="@id/toolbar"
        local:MvxBind="Text Strings[CityTextView]" />
    <MvxSpinner
        android:id="@+id/select_city"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_marginBottom="24dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:spinnerMode="dropdown"
        android:layout_below="@id/city"
        local:MvxItemTemplate="@layout/item_city"
        local:MvxDropDownItemTemplate="@layout/item_city"
        local:MvxBind="ItemsSource Cities; SelectedItem SelectedCity" />

And item_city.axml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">
    <ImageView
        android:id="@+id/cityImage"
        android:layout_width="35dp"
        android:layout_height="20dp"
        android:layout_marginLeft="16dp"
        android:scaleType="fitXY"
        local:MvxBind="DrawableName Name, Converter=IconsConverter" /> />
    <TextView
        android:id="@+id/cityName"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_marginLeft="8dp"
        android:layout_toRightOf="@id/cityImage"
        android:textSize="16sp"
        local:MvxBind="Text Name" />
</RelativeLayout>

In the Core, I have City.cs:

namespace My.cities.Core.Models
{
    public class City
    {
        public City(string Id, string Name, string Flag)
        {
            this.Id = Id;
            this.Name = Name;
            this.Flag = Flag;
        }
        public string Id { get; set; }
        public string Name { get; set; }
        public string Flag { get; set; }
    }
}

And MypageViewModel.cs:

using MvvmCross.Core.ViewModels;
using System.Collections.Generic;
using My.cities.Core.Models;

namespace My.cities.Core.ViewModels
{

    public class MypageViewModel : BaseViewModel
    {

    private City _selectedCity;

    private List<City> _cities = new List<City>()
    {
        new City("1", "London", "England")
        new City("2", "Paris", "France")
    };

    public List<City> Cities
    {
        get { return _cities; }
    }

    public City SelectedCity
    {
        get
        {
            return _selectedCity;
        }
        set
        {
            _selectedCity = value;
            RaisePropertyChanged(() => SelectedCity);
        }
    }
}
}

So I add the converter to MypageView.cs:

using Android.App;
using MvvmCross.Platform.Converters;
using System;
using System.Globalization;

namespace My.cities.Droid.Views
{   [Activity]
    class MypageView : BaseView
    {
        protected override int LayoutResource => Resource.Layout.MypageView;

        protected override void OnCreate(Bundle bundle)
        {
        base.OnCreate(bundle);
        }

        public static class CrossDeviceInfoHelper
        {
            public static string GetLocalImageUrlByPlatform(string name)
            {

                return CrossDeviceInfo.Current.Platform == Platform.Android ? $"@drawable/{name}" : name;
            }
        }

        public class IconsConverter : MvxValueConverter<string, string>
        {
            protected override string Convert(string value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value == "London")
        return CrossDeviceInfoHelper.GetLocalImageUrlByPlatform("england");
                if (value == "Paris")
        return CrossDeviceInfoHelper.GetLocalImageUrlByPlatform("france");
         }
    }

Images England.png and France.png live here: My.sities.Droid\Resources\drawable-hdpi, My.sities.Droid\Resources\drawable-mdpi, and etc.

The build is successful, but I can't see my images, only empty rectangles. Why?

UPD.

I installed Xam.Plugin.DeviceInfo and changed my code. But I still can't see icons.

In debug it says:

[0:] MvxBind:Warning: 36,05 Value '' could not be parsed as a valid string identifier
[0:] MvxBind:Warning: 36,06 Value '' could not be parsed as a valid string identifier
[0:] MvxBind:Warning: 36,06 Value 'London' was not a known drawable name
[0:] MvxBind:Warning: 36,08 Value 'Paris' was not a known drawable name

UPD2.
Also, I tried to do it this way:

public class IconsConverter : MvxValueConverter<string, int>
        {
            protected override int Convert(string value, Type targetType, 
object parameter, CultureInfo culture)
            {
                switch (value)
                {
                    case "London":
                        return Resource.Mipmap.England;
                    case "Paris":
                        return Resource.Mipmap.France;
                }
            }
        }

But the error is the same:

[0:] MvxBind:Warning: 9,54 Value '' could not be parsed as a valid string identifier [0:] MvxBind:Warning: 9,63 Value '' could not be parsed as a valid string identifier [0:] MvxBind:Warning: 9,64 Value 'London' was not a known drawable name [0:] MvxBind:Warning: 9,65 Value 'Paris' was not a known drawable name

NaSt
  • 301
  • 1
  • 5
  • 16
  • Do you maybe not need to make you `MypageView` class `public` if the converter is a child class? I'm not sure if the converter will be picked up in the sweep to find converters if the class is not public. – Plac3Hold3r Jan 25 '18 at 18:42

2 Answers2

2

I think you are lacking the android:scaleType in your ImageView. Try using android:scaleType="fitXY".

If it is not that, try using the DrawableName binding instead of DrawableId and it's better because you can use a converter in your PCL making it cross-platform with Xam.Plugin.DeviceInfo and a helper method like this one:

public static class CrossDeviceInfoHelper
{
    public static string GetLocalImageUrlByPlatform(string name)
    {
        // Assuming we are working with Android and iOS
        return CrossDeviceInfo.Current.Platform == Platform.Android ? $"@drawable/{name}" : name;
    }
}

So you'll endup with a Converter like this one:

public class StringToIntValueConverter : MvxValueConverter<string, string>
{
    protected override string Convert(string value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == "London")
            return CrossDeviceInfoHelper.GetLocalImageUrlByPlatform("england");
        if (value == "Paris")
            return CrossDeviceInfoHelper.GetLocalImageUrlByPlatform("france");
    }
}

Also if I were you I'll add an enum or something that tells you the country in your City class so that you don't have to compare strings in the converter and you could also have a Dictionary in your converter that has which city goes with which country image so that you can just call CrossDeviceInfoHelper.GetLocalImageUrlByPlatform(myDictionary[value]); and therefore not using ifs

fmaccaroni
  • 3,846
  • 1
  • 20
  • 35
  • Thank you again! I installed `Xam.Plugin.DeviceInfo` and tested this solution. I changed `item_city` and `View.cs`. But for some reason, I still can't see icons. I edited my post and added error message – NaSt Jan 25 '18 at 15:15
  • It works but values are interchanged with each other. How can it be? O_o – NaSt Jan 25 '18 at 19:42
  • Have you checked the images are named correctly? and the items are correctly set? – fmaccaroni Jan 25 '18 at 21:55
0

The binding expression DrawableName Name Converter=IconsConverter is wrong. You are missing a comma:

DrawableName Name, Converter=IconsConverter

Alternatively you can write it like:

DrawableName Icons(Name)
Cheesebaron
  • 24,131
  • 15
  • 66
  • 118
  • I tried to use `DrawableName Icons(Name)` but the error is ```MvxBind:Error: 10,09 Failed to find combiner or converter for Icons MvxBind:Warning: 10,09 Value '' could not be parsed as a valid string identifier``` – NaSt Jan 25 '18 at 16:28
  • After that I tried `DrawableName Name, Converter=IconsConverter`, but also have an error. It seems I missed something in names. I'll edit the post – NaSt Jan 25 '18 at 16:29