Eugene Sukhomlyn
Eugene Sukhomlyn

Reputation: 45

Click event RecyclerView doesn't works (Xamarin)

I have recycler view

I need to open activity by click on element on recycler view

I do it like this in Adapter

  public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {
        var layout = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.MovieRow, parent, false);

        return new MovieViewHolder(layout, OnItemClick);

    }

    public override int ItemCount
    {
        get { return movies.Count; }
    }

    void OnItemClick(int position)
    {
        if (ItemClick != null)

          // _context.StartActivity(typeof(Register));

           ItemClick(this, position);
    }

And like this on ViewHolder

 public MovieViewHolder(View itemView, Action<int> listener) : base(itemView)
    {
        MovieNameTextView = itemView.FindViewById<TextView>(Resource.Id.movieNameText);
        DirectedByTextView = itemView.FindViewById<TextView>(Resource.Id.directedByText);
        Image = itemView.FindViewById<ImageView>(Resource.Id.image);
        itemView.Click += (s, e) => listener(Position);

    }

But when I click on element in Recycler View , nothing happens, where is my problem?

Upvotes: 0

Views: 412

Answers (1)

Cheesebaron
Cheesebaron

Reputation: 24470

It is a bit unclear what you do with your ItemClick and how you propagate it up to the surface.

So first of all, in your MovieViewHolder you want add an EventHandler to your item view's Click event, just like you've shown. You should also remember to remove the event subscription again, preferably in Dispose so that you don't leak memory.

So something like:

public MovieViewHolder(View itemView, ...) : base(itemView)
{
    ItemView.Click += OnItemClick;
}

private void OnItemClick(object s, EventArgs e)
{
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        ItemView.Click -= OnItemClick;
    }
}

Then I'd probably just use ICommand like most MVVM frameworks do, to propagate actions.

public ICommand ItemClick
{
    get; set;
}

Then in OnItemClick invoke the command:

private void OnItemClick(object s, EventArgs e)
{
    if (ItemClick == null) return;
    if (ItemClick.CanExecute(null))
        ItemClick.Execute(null);
}

Then in your RecyclerView.Adapter implementation you would assign the command in OnCreateViewHolder:

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{

    var vh = new MovieViewHolder(...)
    {
        Click = ItemClick
    };

    return vh;
}

Your Adapter would also have a ItemClick ICommand property which you set from your View where you create it.

public ICommand ItemClick {get; set;}

In your View:

var recycler = FindViewById<RecyclerView>(...);
var adapter = new MovieAdapter {
    ItemClick = ViewModel.ItemClick
};

ViewModel.ItemClick here is just an instance of your implementation of ICommand. If you wan't you can change ICommand to Action instead or something like that to get a callback instead.

Just keep in mind, if you change the MovieAdapter.ItemClick after at runtime at a later point, after a bunch of ViewHolder's have been created, you would cause inconsistencies as the old ViewHolder's would be pointing at your old ItemClick.

Upvotes: 1

Related Questions