MvvmCross, Mvx.MvxListView and user binding in MvxItemTemplate

In the MvvmCross application, I have a page with the classic chat behavior (WhatsApp like): this page displays the history of messages exchanged between two users, with the last message at the bottom of the list. I have successfully implemented the view in Windows Phone 8.1, but I'm struggling with a problem in Android.

I will give you a brief introduction and description of my problem, and then I will look at the technical details.

Introduction

Actually, my need is to apply different styles to messages sent by different users: it is typical to align left messages sent from another user and align the correct messages sent by me (I do this through a property weight); I need to apply a different background drawableand set a different property gravity. I use custom binding because, AFAIK, these properties cannot be bound to classic binding: it local:MvxBind="Gravity MyPropery"does not work because there is no Gravity property.

So, I have, of course, two axml files:

  • the first one contains Mvx.MvxListView
  • the second contains an element template for MvxListView

And I created three different user bindings (for background, gravity and weight) in the following manuals:

, , , . , .

, , : , , .

, , : ( , , ), . . , , .

DEBUG

, , .

public class LinearLayoutWeightTargetBinding : MvxAndroidTargetBinding
{
    public static int debugCounter = 0;
    public LinearLayoutWeightTargetBinding(object target) : base(target)
    {
    }

    protected LinearLayout MyTarget
    {
        get { return (LinearLayout)Target; }
    }

    public override Type TargetType { get { return typeof(bool); } }

    protected override void SetValueImpl(object target, object value)
    {
        var ll = (LinearLayout)target;
        var itsMe = (bool)value;
        var weight = itsMe ? (float)20.0 : (float)5.0;

        var layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WrapContent, weight);
        ll.LayoutParameters = layoutParams;
        Log.Debug("MeeCHAT", string.Format("LinearLayoutWeightTargetBinding::SetValueImpl::ItsMe:{0} - counter:{1}", itsMe, ++debugCounter));
    }

    public override MvxBindingMode DefaultMode { get {return MvxBindingMode.TwoWay;} }
}

, , (debugCounter ). , , , 10 , , . , 10 , ( ), .

, . .

, http://gregshackles.com/presenters-in-mvvmcross-navigating-android-with-fragments/ Activity Fragment View; a Presenter ViewModel .

, Mvx.MvxListView,

public class MyMatchersChatView : MvxFragment
{
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignore = base.OnCreateView(inflater, container, savedInstanceState);
        var result = this.BindingInflate(Resource.Layout.MyMatchersChatView, null);

        var headerFrame = result.FindViewById<FrameLayout>(Resource.Id.headerFrameMyMatchersChatView);
        var headerWidget = new HeaderWidget() { ViewModel = this.ViewModel };
        var tran = ChildFragmentManager.BeginTransaction();
        tran.Add(headerFrame.Id, headerWidget, "headerMyMatchersChat");
        tran.Commit();

        var listView = result.FindViewById<MvxListView>(Resource.Id.messagesList);
        listView.SetSelection(listView.Adapter.Count - 1); // Scroll to the end of the list
        return result;
    }        
}

listView.SetSelection(listView.Adapter.Count - 1); .

: axml.

Setup.cs :

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
    base.FillTargetFactories(registry);
    registry.RegisterFactory(new MvxCustomBindingFactory<LinearLayout>("CustomWeight",
            (b) => new LinearLayoutWeightTargetBinding(b)));
}

axml :

<LinearLayout 
  android:orientation="horizontal" 
  android:layout_width="0dp" 
  android:layout_height="wrap_content" 
  local:MvxBind="CustomWeight IsCurrentUser">

LISTVIEW VIEWMODEL

ListView

<Mvx.MvxListView
  android:id="@+id/messagesList"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  local:MvxBind="ItemsSource MyMessages"
  local:MvxItemTemplate="@layout/mymatcherschatview_itemtemplate" />

ViewModel

    private IEnumerable<MyMatchMessageModel> _myMessages;
    public IEnumerable<MyMatchMessageModel> MyMessages
    {
        get { return _myMessages; }
        set
        {
            _myMessages = value;
            RaisePropertyChanged(() => MyMessages);
        }
    }

, :

  • Visual Studio 2015
  • MvvmCross 3.5.1
  • :.NET Framework 4.5, Windows 8, ASP.NET Core 5.0, Windows Phone 8.1, Xamarin.Android, Xamarin.iOS, Xamarin.iOS().
  • Android- API- 19 ( Xamarin.Android v4.4).
  • Xamarin 3.11.1450.0
  • Xamarin.Android 5.1.6.7

- , - ? !

→ EDIT 1 <

, stackFromBottom transcriptMode Fragment, , : ( )

axml...

<Mvx.MvxListView
  android:id="@+id/messagesList"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:stackFromBottom="true"
  android:transcriptMode="alwaysScroll"
  local:MvxBind="ItemsSource MyMessages"
  local:MvxItemTemplate="@layout/mymatcherschatview_itemtemplate" />

...

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
  var ignore = base.OnCreateView(inflater, container, savedInstanceState);
  var result = this.BindingInflate(Resource.Layout.MyMatchersChatView, null);

  var headerFrame = result.FindViewById<FrameLayout>(Resource.Id.headerFrameMyMatchersChatView);
  var headerWidget = new HeaderWidget() { ViewModel = this.ViewModel };
  var tran = ChildFragmentManager.BeginTransaction();
  tran.Add(headerFrame.Id, headerWidget, "headerMyMatchersChat");
  tran.Commit();

  return result;
}   
+4
1

, , , . SetValueImpl() , . , , - , . , , (, ) MvxAdapter.

, . ChatListAdapter : MvxAdapter :

public class CoolChatListAdapter : MvxAdapter
{
    public CoolChatListAdapter(Context context, IMvxAndroidBindingContext bindingContext) : base(context, bindingContext)
    {
    }

    protected override View GetBindableView(View convertView, object source, int templateId)
    {
        var item = source as MyMatchMessageModel;
        var weight = item.IsCurrentUser ? (float) 20.0 : (float) 5.0;

        var ll = (LinearLayout) convertView;
        var layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WrapContent, weight);
        ll.LayoutParameters = layoutParams;

        return base.GetBindableView(convertView, source, templateId);
    }
}

android:

var adapter = new ChatListAdapter(this, (IMvxAndroidBindingContext)BindingContext);
_chatList = FindViewById<MvxListView>(Resource.Id.chat_list_view);
_chatList.Adapter = adapter;
0

Source: https://habr.com/ru/post/1623524/


All Articles