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);
}