Return ImageView instance when i click on the item

2019-07-15 05:03发布

问题:

How to return ImageView instance when i click on the item GridView?

I create custom bindings event for ItemClick:

public class ItemClickSquareBinding
        : MvxBaseAndroidTargetBinding
    {
        private readonly GridView _gridView;
        private IMvxCommand _command;

        public ItemClickSquareBinding(GridView gridView)
        {
            _gridView = gridView;
            _gridView.ItemClick += GridView_ItemClick;
        }

        private void GridView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            //----->Get ImageView
        }

        public override void SetValue(object value)
        {
            _command = (IMvxCommand)value;
        }

        protected override void Dispose(bool isDisposing)
        {
            if (isDisposing)
            {
                _gridView.ItemClick -= GridView_ItemClick;
            }
            base.Dispose(isDisposing);
        }

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

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

My GridView:

<cirrious.mvvmcross.binding.android.views.MvxBindableGridView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:numColumns="4"
        android:gravity="center"
        android:listSelector="#00000000"
        local:MvxItemTemplate="@layout/itemimage"
        local:MvxBind="{'ItemsSource':{'Path':'Squares'}, 'ClickItemSquare':{'Path':'ClickCommand'}}" />

My ImageView:

<ImageView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:local="http://schemas.android.com/apk/res/LeSommet.ZooSnap.UI.Android"
      android:layout_width="80dp"
      android:layout_height="80dp"
      android:padding="5dp"
      android:layout_gravity="center"
      local:MvxBind="{'ResourcesImagePath':{'Path':'ImagePath'}}"
  />

How to return ImageView instance when i click on the item GridView? (or how I may return instance of object which clicked me)

回答1:

Three answers below ... I prefer the one marked 3

1) A Simpler Approach

At a really basic level, I think you can just use the built-in binding for this.

Looking at ItemClick in https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Binding.Droid/Views/MvxBindableGridView.cs you should be able to just do:

<cirrious.mvvmcross.binding.android.views.MvxBindableGridView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="4"
    android:gravity="center"
    android:listSelector="#00000000"
    local:MvxItemTemplate="@layout/itemimage"
    local:MvxBind="{'ItemsSource':{'Path':'Squares'}, 'ItemClick':{'Path':'ClickCommand'}}" />

where ClickCommand is something like:

public ICommand ClickCommand { get { return new MvxRelayCommand<Square>(square => square.Foo()); } }

If this doesn't work, then please raise a bug with test code - the grid was community donated to MvvmCross so it's not something I've used yet.


2) To make your custom binding work

If you do want to do the custom binding.

Using Intellisense, it looks like an AdapterView.ItemClickEventArgs has a couple of potentially useful properties:

        e.View;
        e.Position;

So you can access the View if you want to - and can then use things like FindViewById<> to find contained views.

Or you can access the Position and can then: - use Adapter methods like public override Object GetItem(int position) to get a Java wrapped object from your original array - or can use accessor method direct on your incoming array or enumerable.


3) The way I normally work

I generally don't do this sort of custom binding when all I want to do is click on a list item or part of a list item.

Instead I write my ViewModels so that they expose behaviour-enabled collections - I try to present a behaviour-enabled wrapper of the Model object rather than the Model object itself.

In this approach the ViewModel exposes a List<WrappedSquare> instead of a List<Square>

public WrappedSquare
{
   Square _saure;
   SquareViewModel _square;

   public WrappedSquare(Square square, SquareViewModel parent)
   {
       /* assignment */
   }

   public ICommand TheCommand { get { return MvxRelayCommand(() -> _parent.DoStuff(_square)); } }

   public Square TheSquare { get { return _square; } } 
}

The axml within the list item then has bindings like:

<ImageView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:local="http://schemas.android.com/apk/res/LeSommet.ZooSnap.UI.Android"
      android:layout_width="80dp"
      android:layout_height="80dp"
      android:padding="5dp"
      android:layout_gravity="center"
      local:MvxBind="{'ResourcesImagePath':{'Path':'TheSquare.ImagePath'},'Click':{'Path':'TheCommand'}}"
  />

and the axml for the grid is:

<cirrious.mvvmcross.binding.android.views.MvxBindableGridView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="4"
    android:gravity="center"
    android:listSelector="#00000000"
    local:MvxItemTemplate="@layout/itemimage"
    local:MvxBind="{'ItemsSource':{'Path':'WrappedSquares'}}" />

This example code is adapted from MVVMCross changing ViewModel within a MvxBindableListView - the answer there is relevant to this question too.


One real example of this approach is the Conference sample which uses WithCommand<T> to enable navigation from lists to detail views.

However... there is one warning on this approach - please note that when using WithCommand<T> we discovered a memory leak in iOS/MonoTouch - basically the GarbageCollection refused to collect the embedded MvxRelayCommand - which is why WithCommand<T> is IDisposable and why BaseSessionListViewMode clears the list and disposes the WithCommand elements when views are detached.



回答2:

A fourth answer (after comment on previous three...)

Bindings are about View-ViewModel communication.

Animation is not something the ViewModel or the Binding should really handle.

In my opinion, you would be better off using a custom control for your animation. For custom controls in MonoDroid, see Xamarin Monodroid: WP7 => Android and Custom Control?