Android MVVM Cross v3 - How to Create a ListView w

2019-06-03 03:34发布

问题:

I'd like to create a ListView that has an alternating background colour for each row.

I'm new to Android development in general, never mind Xamarin and MVVMCross as well :)

There are some examples of doing this in the Android world and the Xamarin world, but I can't figure out how to set this up in an MVVM Cross way.

My understanding is that I will need to implement this in the Android specific view code and to do that I will need to set some adapter on the ListView that can programatically set the background colour of each List item as they are rendered.

I found this example:

https://github.com/slodge/MvvmCross-Tutorials/tree/master/Working%20With%20Collections/Collections.Droid

However, once implemented I find that none of the following methods are called on my CustomAdapter : MvxAdapter when displaying the view:

GetBindableView, GetSimpleView, GetBindableView, GetView

I also found this unanswered question

Issue with custom listview using mono droid and mvvmcross

Which uses MvxBindableListAdapter which seems no longer to exist.

Can anyone point me in the right direction?

Here are the various code snippets involved:

TradeBookingResponseView.axml owns this:

<Mvx.MvxListView
  android:id="@+id/TradeConfirmation"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  local:MvxBind="ItemsSource OpenTradeListItems"
  local:MvxItemTemplate="@layout/item_confirmation"
/>

inside its LinearLayout

item_confirmation.axml is this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/tradingStateIcon"
    xmlns:local="http://schemas.android.com/apk/res-auto">
    <TextView
      android:layout_weight="0.35"
      android:text="Field"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_marginLeft="10dip"
      android:id="@+id/tradeConfirmationField"
      local:MvxBind="Text Field" />
    <TextView
      android:layout_weight="0.65"
      android:text="Value"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:id="@+id/tradeConfirmationValue"
      local:MvxBind="Text Value"/>
</LinearLayout>

The TradeBookingResponseViewModel exposes this

public ObservableCollection<ConfirmationItem> OpenTradeListItems
{
    get
    {
        return openTradeListItems;
    }
    set
    {
        if (!Equals(value, openTradeListItems))
        {
            openTradeListItems = value;
            RaisePropertyChanged(() => OpenTradeListItems);
        }
    }
}

While the view code is

public class TradeBookingResponseView : ViewBase
{
    public TradeBookingResponseView() : base(Resource.Layout.TradeBookingResponseView)
    {

    }

    protected override void OnViewModelSet()
    {
        SetContentView(Resource.Layout.TradeBookingResponseView);
        var list = FindViewById<ListView>(Resource.Id.TradeConfirmation);
        list.Adapter = new CustomAdapter(this, (IMvxAndroidBindingContext) BindingContext);
    }
}

public class CustomAdapter : MvxAdapter
{
    public CustomAdapter(Context context) : base(context)
    {
    }

    public CustomAdapter(Context context, IMvxAndroidBindingContext bindingContext) : base(context, bindingContext)
    {
    }

    protected override View GetBindableView(View convertView, object dataContext)
    {
        convertView.SetBackgroundColor(Color.Red);
        return base.GetBindableView(convertView, dataContext);
    }
}

Where ViewBase extends MvxActivity

And I'm setting red just to see if it gets called (it doesn't). According to more Android-y examples I want to use View GetView(int position, View convertView, ViewGroup parent) to see what position the item is at, so I can do % 2 on it (this also is not called).

回答1:

Try setting the color after the base method - eg

public override GetView(int position, View convertView, ViewGroup parent) 
{
      var v = base.GetView(position, convertView, parent);
      v.SetBackgroundColor( I %2 == 0 ? Color.Red : Color.Blue);
      return v;
}

Alternatively you could data-bind the background color if you wanted to



回答2:

Here is how to data-bind using background, in your custom table template (item_confirmation), replace my RowItem.RowId with the id of your OpenTradeListItems list:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    ...
    local:MvxBind="BackgroundColor BackgroundColor(RowItem.RowId)">

And here is the BackgroundColor converter:

public class BackgroundColorValueConverter : MvxColorValueConverter
{
    protected override MvxColor Convert(object value, object parameter, System.Globalization.CultureInfo culture)
    {
        return (int)value % 2 != 0 ? BusinessConstants.ThirdAlternateBGColor : null;
    }
}