How to set Tag for a view inside GetCellCore of CellRenderer ?

I have a Custom CellRenderer ( Android ) for list items in a Xamarin.Forms.ListView.

I am trying to create a custom ViewHolder pattern , so that I can get rid of unnecessary view.FindViewById calls.

Here is my code :

`[assembly: ExportRenderer (typeof (CommentsListItem), typeof (CommentsListItemCellRenderer))]
namespace TCMobile.Droid
{
public class ViewHolder : Java.Lang.Object{
public ImageView commentDeleteImage;
public TextView commentDescription;
public TextView commentAuthor;
public TextView commentModified;
}

public class CommentsListItemCellRenderer : CellRenderer
{

    Android.Views.View view;
    Activity activity = null;
    ViewHolder holder = null;

    private bool assignDelegate = false;



    public CommentsListItemCellRenderer ()
    {
    }

    protected override Android.Views.View GetCellCore (Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
    {
        base.GetCellCore (item, convertView, parent, context);
        assignDelegate = false;

        view = convertView;
        var x = (CommentsListItem)item;

        activity = context as Activity;
        if (view == null) {// no view to re-use, create new
            assignDelegate = true;
            view = activity.LayoutInflater.Inflate (Resource.Layout.TodoCommentsListCell, null);

            holder = new ViewHolder ();
            holder.commentDeleteImage = view.FindViewById<ImageView> (Resource.Id.comments_delete_image);
            holder.commentDescription = view.FindViewById<TextView> (Resource.Id.comments_text); 
            holder.commentAuthor = view.FindViewById<TextView> (Resource.Id.comments_username); 
            holder.commentModified = view.FindViewById<TextView> (Resource.Id.comments_modified);

            view.Tag = holder;

        } else {
            // PROBLEM IN THIS LINE
            holder = (ViewHolder) view.Tag;
        }

        FontHelper.getFontHelper().applyFont(holder.commentAuthor, Constants.FONT_OPEN_SANS_BOLD);
        FontHelper.getFontHelper().applyFont(holder.commentDescription, Constants.FONT_OPEN_SANS_REGULAR);
        FontHelper.getFontHelper().applyFont(holder.commentModified, Constants.FONT_OPEN_SANS_REGULAR);

        holder.commentDescription.Text = x.CommentsText;
        holder.commentAuthor.Text = x.AuthorName;
        holder.commentModified.Text = x.CreatedDate;

        if (x.EditEnabled) {
            holder.commentDeleteImage.Visibility = Android.Views.ViewStates.Visible;
        } else {
            holder.commentDeleteImage.Visibility = Android.Views.ViewStates.Gone;
        }

        if (assignDelegate) {
            holder.commentDeleteImage.Click += delegate {
                if (x.EditEnabled) {
                    MessagingCenter.Send<CommentsListItemCellRenderer, string> (this, "DeleteComment", x.CommentId);
                }
            };
        }

        return view;
    }



}

}
`

The problem is , in case of reused views i.e. when convertView is not null , I am getting an InvalidCastException in the line ,
holder = (ViewHolder) view.Tag;

I have also tried holder = view.Tag as ViewHolder .
But it returned null value .
Also, I do not know how the view.SetTag(int, Object) method can be useful in this case.

Is there any other way to do this , within the Cell Renderer ?

Answers

  • mr_javichomr_javicho ESMember ✭✭

    Hi! I came across the same problem a few days ago. I still cant understand why this happens. By some some reason, when a non visible entry of the listview becomes visible, (ViewHolder) view.Tag throws a InvalidCastException. This has only happened to me using Xamarin Forms. What I've done is to set the tag using SetTag method instead of the Tag property:

    view.SetTag(Resource.Id.holderTagId, holder)

    then getting it back using:

    holder = (ViewHolderClass)view.GetTag(Resource.Id.holderTagId);

    You must use an unique identifier. I usually have a ids.xml file in my Values folder, you can define one using
    <item type="id" name ="myIdName"/>

    This is the only way i could get it to work. Hope it helps to anyone trying to re use their custom cells.

  • Thanks @mr_javicho . It worked..

  • @mr_javicho : I am using a single unique ID as view holder tag, for a listview (same id for all list items). Will that create any problems ?

Sign In or Register to comment.