MvxListView create binding for template layout from code

放肆的年华 提交于 2019-12-17 16:08:22

问题


Lets say I have a simple Layout with a MvxListView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/LiivControl.Client.Droid"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Mvx.MvxListView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        local:MvxBind="ItemsSource AutoListItems; ItemClick AutoListItemClicked"
        local:MvxItemTemplate="@layout/vbmvxautoviewlistitem" />
</LinearLayout>

My item template layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/LiivControl.Client.Droid"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="10dip"
    android:paddingBottom="10dip"
    android:paddingLeft="15dip">
    <TextView
        android:id="@+id/list_complex_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    <TextView
        android:id="@+id/list_complex_caption"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>

I would like to specify the bindings for the two textview elements in my itemtemplate from code behind. I am not sure how best to go about it. I'm guess I could do something "OnViewModelSet" in the view code behind of the MvxListView. I have tried the following but for it obviously doesn't work because it can't find the control.

protected override void OnViewModelSet()
    {
        IVbMvxAutoListViewModel vm = base.ViewModel as IVbMvxAutoListViewModel;

        TextView title = this.FindViewById<TextView>(Resource.Id.list_complex_title);
        this.CreateBinding(title).For(x => x.Text).To(vm.ListItemDescriptor.TitlePropName).Apply();

        TextView subTitle = this.FindViewById<TextView>(Resource.Id.list_complex_caption);
        this.CreateBinding(subTitle).For(x => x.Text).To(vm.ListItemDescriptor.SubTitlePropName).Apply();
        base.OnViewModelSet();
    }

My other thought was to somehow intercept the oncreate for the itemtemplate view but OnCreate doesn't get called if I create a view code file for my itemtemplate layout.


回答1:


To do the bindings in code it's probably best to:

  1. implement a custom MvxListViewItem
  2. implement a custom MvxAdapter to return the custom list view item
  3. implement a custom MvxListView to use the custom MvxAdapter

Not tested, but the code for this is roughly:

1. implement a custom MvxListViewItem

public class CustomListItemView
    : MvxListItemView
{
    public MvxListItemView(Context context,
                           IMvxLayoutInflater layoutInflater,
                           object dataContext,
                           int templateId)
        : base(context, layoutInflater, dataContext, templateId)
    {
        var control = this.FindViewById<TextView>(Resource.Id.list_complex_title);
        var set = this.CreateBindingSet<CustomListViewItem, YourThing>();
        set.Bind(control).To(vm => vm.Title);
        set.Apply();
    }
}

2. Create a custom MvxAdapter

In this override CreateBindableView

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

    protected override IMvxListItemView CreateBindableView(object dataContext, int templateId)
    {
        return new CustomListItemView(_context, _bindingContext.LayoutInflater, dataContext, templateId);
    }
}

original: https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Droid/Views/MvxAdapter.cs#L298

3. implement a custom MvxListView to use the adapter

This should be as simple as:

public class CustomListView
    : MvxListView
{
    public CustomListView(Context context, IAttributeSet attrs)
        : base(context, attrs, new CustomAdapter(context))
    {
    }
}

As long as this is in your main UI assembly, this should be useable in your axml as:

<CustomListView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    local:MvxBind="ItemsSource AutoListItems; ItemClick AutoListItemClicked"
    local:MvxItemTemplate="@layout/vbmvxautoviewlistitem" />

If CustomListView is not in your main UI assembly, then there are some tricks to get MvvmCross to pick it up during your Setup - see Providing Custom Android View Assemblies in https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup#wiki-providing-custom-views-android


The above is the best way to do this (IMO) - but if you wanted to, then you could do it in less code by just applying the bindings inside the custom adapter and by setting that adapter in OnCreate in your Activity



来源:https://stackoverflow.com/questions/21515976/mvxlistview-create-binding-for-template-layout-from-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!