You can change the layout of the spinner (hence the style) directly in axml via two attributes:
local:MvxItemTemplate: Sets the layout of the selected item.
local:MvxDropDownItemTemplate: Sets the layout of each item in the dropdown
So given a ViewModel with a collection CategoryGroups and the SelectedCategoryGroup, i.e.:
public class MyViewModel : MvxViewModel
{
...
public ObservableCollection<CategoryGroup> CategoryGroups { get; set; }
public CategoryGroup CategoryGroupdSelected { get; set; }
...
}
and the CategoryGroup class:
public class CategoryGroup
{
public int Id { get; set; }
public string Name { get; set; }
}
You can bind the collection to a spinner like this:
<MvxSpinner
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:theme="@style/Spinner"
local:MvxItemTemplate="@layout/my_spinner_item"
local:MvxDropDownItemTemplate="@layout/my_spinner_dropdown_item"
local:MvxBind="ItemsSource CategoryGroups; SelectedItem CategoryGroupdSelected" />
and in each template you define the layout/style of the item. Take into account that in the templates their DataContext is an item (in this case a CategoryGroup). In my example, I want to display the Name of each CategoryGroup then I just need a TextView and bind its Text property to the Name of the CategoryGroup, i.e. the item's DataContext:
my_spinner_item.axml:
<?xml version="1.0" encoding="utf-8"?>
<TextView 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="wrap_content"
android:layout_marginLeft="5dp"
android:textColor="@android:color/black"
android:textSize="25sp"
local:MvxBind="Text Name" />
my_spinner_dropdown_item.axml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textColor="@android:color/black"
android:alpha="0.8"
local:MvxBind="Text Name" />
Now if you want all of your spinner to have the same templates you can just set a style with those attributes or you can inherit MvxSpinner and set the templates programmatically.
Apart from that if you want to use one of each template and not create one per each different binding you could have a base class BaseItemViewModel with an abstract property named Description and use that to bind in the View. So that in your VMs you always inherit from BaseItemViewModel and override Description property to have the value you want to display.
public abstract class BaseItemViewModel : MvxNotifyPropertyChanged
{
public abstract string Description { get; }
}
Another way is to have a WrappedItemViewModel where you pass the object T you want to be in the spinner and a Func<T, string> that returns what the spinner displays (the description) and you have a Description property that just invokes the Func<T, string>. This way has the advantage that it doesn't make you inherit always from a VM and you can wrap almost any object in it adding the behaviour to be in a Spinner.
public class WrappedItemViewModel<T> : MvxNotifyPropertyChanged
{
private readonly Func<T, string> descriptionFunc;
public WrappedItemViewModel(T item, Func<T, string> descriptionFunc)
{
this.MyItem = item;
this.descriptionFunc = descriptionFunc;
}
public T MyItem { get; }
public string Description => this.descriptionFunc.Invoke(this.MyItem);
}