CardView 中的 Xamarin Recyclerview 按钮,无法获得位置

Xamarin Recyclerview Buttons In CardView, cant get Position

我有一个大问题(对我来说,我希望你在 Xamarin 中做得更好;))

我有一个 Recyclerview 和一个适配器,就像 Xamarin 示例一样,所以现在在新的 Projekt 中,我需要 CardView 的 2 个。按钮一个用于 + 另一个 -,我正在让两个按钮工作但不是真的很好,因为很多时候 + 没有在错误的 CardView 上执行正确的操作。

问我是否需要更多输入,我现在很困惑:/

这是我的代码:

BelPOSAdapter.cs:

public ArtikelDaten(string BELidxRAW, string Mandant)
    {
        BELIdx = BELidxRAW;

        List<.....> WWSVCconnections = Utils.Init(Mandant);

        foreach (..... in WWSVCconnections)
        {
            ..../hier is something that gives me the Json.

            string WWbelPosResp = getRes.Content;

            //JSON in Foreach
            mBuiltInPOS.Clear();
            dynamic dynPOSJson = JsonConvert.DeserializeObject(WWbelPosResp);
            foreach (var POSitem in dynPOSJson["POSITIONSLISTE"]["POSITION"])
            {
                mBuiltInPOS.Add(new Artikel
                {
                    //Info, KEINE anzeige
                    mARTBELart = POSitem["POS_2_1"].ToString(),
                    mARTBELnr = POSitem["POS_3_8"].ToString(),

                    //Anzeige
                    mARTBELlfdnr = POSitem["POS_11_6"].ToString(),

                    mARTnr = POSitem["POS_18_25"].ToString(),
                    mARTbezeichnung = POSitem["POS_45_60"].ToString(),
                    mARTretourMenge = "0",
                    mARTmenge = POSitem["POS_164_8"].ToString(),
                    mARTeinheit = " " + POSitem["POS_689_5"].ToString()
                });
            }
        }

        mArtikel = mBuiltInPOS.ToArray();

ScanPositionenActivity.cs:

 public class POSViewHolder : RecyclerView.ViewHolder
    {
        //1public ImageView Image { get; private set; }
        public TextView ARTnr { get; private set; }
        public TextView ARTbezeichnung { get; private set; }
        public TextView ARTmenge { get; private set; }
        public TextView ARTretourMenge { get; private set; }

        public TextView ARTBELnr { get; private set; }
        public TextView ARTBELart { get; private set; }
        public ImageButton ARTminus { get; set; }
        public ImageButton ARTplus { get; set; }
        public TextView ARTBELlfdnr { get; private set; }

        // Get references to the views defined in the CardView layout.
        //public POSViewHolder(View itemView, Action<int> listener) : base(itemView)
        public POSViewHolder(View itemView, Action<int> listener) : base(itemView)
        {


            // Locate and cache view references:
            //1Image = itemView.FindViewById<ImageView>(Resource.Id.imageView);
            ARTnr = itemView.FindViewById<TextView>(Resource.Id.LBLartNr);
            ARTbezeichnung = itemView.FindViewById<TextView>(Resource.Id.LBLartBezeichnung);
            ARTmenge = itemView.FindViewById<TextView>(Resource.Id.LBLartMenge);
            ARTretourMenge = itemView.FindViewById<TextView>(Resource.Id.LBLretourMenge);


            ARTBELnr = itemView.FindViewById<TextView>(Resource.Id.LBL_kommission_belnr);
            ARTBELart = itemView.FindViewById<TextView>(Resource.Id.LBL_kommission_belart);
            ARTBELlfdnr = itemView.FindViewById<TextView>(Resource.Id.LBL_kommission_POSlfdnr);

            // Detect user clicks on the item view and report which item
            // was clicked (by layout position) to the listener:
            itemView.Click += (sender, e) => listener(base.LayoutPosition);
        }
    }

    //----------------------------------------------------------------------
    // ADAPTER

    // Adapter to connect the data set (photo album) to the RecyclerView: 
    public class PhotoAlbumAdapter : RecyclerView.Adapter
    {
        // Event handler for item clicks:
        public event EventHandler<int> ItemClick;

        // Underlying data set (a photo album):
        public ArtikelDaten mPOSdaten;

        // Load the adapter with the data set (photo album) at construction time:
        public PhotoAlbumAdapter(ArtikelDaten photoAlbum)
        {
            mPOSdaten = photoAlbum;
        }

        // Create a new photo CardView (invoked by the layout manager): 
        public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
        {
            // Inflate the CardView for the photo:
            View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.BelPOSview, parent, false);


            ImageButton BTNminus = itemView.FindViewById<ImageButton>(Resource.Id.BTNminus);
            ImageButton BTNplus = itemView.FindViewById<ImageButton>(Resource.Id.BTNplus);
            // Create a ViewHolder to find and hold these view references, and 
            // register OnClick with the view holder:

            //POSViewHolder vh = new POSViewHolder(itemView, OnClick);

            POSViewHolder vh = new POSViewHolder(itemView, OnClick) { ARTminus = BTNminus, ARTplus = BTNplus};

            return vh;
        }

        // Fill in the contents of the photo card (invoked by the layout manager):
        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
        {
            POSViewHolder vh = holder as POSViewHolder;

            // Set the ImageView and TextView in this ViewHolder's CardView 
            // from this position in the photo album:
            //1vh.Image.SetImageResource(mPOSdaten[position].PhotoID);
            vh.ARTnr.Text = mPOSdaten[position].mARTnr;
            vh.ARTbezeichnung.Text = mPOSdaten[position].mARTbezeichnung;
            vh.ARTmenge.Text = mPOSdaten[position].mARTmenge;
            vh.ARTretourMenge.Text = mPOSdaten[position].mARTretourMenge;

            vh.ARTBELnr.Text = mPOSdaten[position].mARTBELnr;
            vh.ARTBELart.Text = mPOSdaten[position].mARTBELart;
            vh.ARTBELlfdnr.Text = mPOSdaten[position].mARTBELlfdnr;

            //RECYCLEVIEW Buttons
            vh.ARTplus.Click -= BTNplus_Click;
            vh.ARTplus.Click += BTNplus_Click;

            vh.ARTminus.Click -= BTNminus_Click;
            vh.ARTminus.Click += BTNminus_Click;
        }

        private void BTNplus_Click(object sender, EventArgs e)
        {
            //int position = this.RecyclerView.GetChildAdapterPosition((View)sender);
            //Toast.MakeText(mContext, vh.ARTretourMenge.Text, ToastLength.Short).Show();
            mPOSdaten[position].mARTretourMenge = (Convert.ToInt32(mPOSdaten[position].mARTretourMenge) + 1).ToString();
            NotifyItemChanged(position);
        }

        private void BTNminus_Click(object sender, EventArgs e)
        {
            if (mPOSdaten[position].mARTretourMenge != "0")
            {
                //Toast.MakeText(mContext, vh.ARTretourMenge.Text, ToastLength.Short).Show();
                mPOSdaten[position].mARTretourMenge = (Convert.ToInt32(mPOSdaten[position].mARTretourMenge) - 1).ToString();
                NotifyItemChanged(position);
            }
        }

所以在 OnBindViewHolder 中,我有我的按钮,当它们被按下时会执行功能,效果不错,但我需要 CardView/Data 的位置,我读到我可以用 int position = this.RecyclerView.GetChildAdapterPosition((View)sender); 但这不起作用我不知道它是如何工作的。

RecyclerView.ViewHolder 有两个有趣的属性:

  • LayoutPosition:给你在布局中的位置。如果您正在执行拖放之类的操作或正在对屏幕上的行重新排序,这很有用。
  • AdapterPosition:为您提供适配器中的位置。这通常会反映您在适配器中使用的数据源中的位置。

由于 sender 对象可能只会为您提供具有点击事件的按钮,因此您需要以某种方式获取 ViewHolder.

一种方法是在 ViewTag 属性 上添加 RecyclerView.ViewHolder 实例。另一种方法是 RecyclerView.ViewHolder 本身具有减号和加号按钮的事件。我个人更喜欢后者。

public class POSViewHolder : RecyclerView.ViewHolder
{
    public event EventHandler MinusClick;
    public event EventHandler PlusClick;

    public TextView ARTnr { get; private set; }
    public TextView ARTbezeichnung { get; private set; }
    public TextView ARTmenge { get; private set; }
    public TextView ARTretourMenge { get; private set; }

    public TextView ARTBELnr { get; private set; }
    public TextView ARTBELart { get; private set; }
    public ImageButton ARTminus { get; set; }
    public ImageButton ARTplus { get; set; }
    public TextView ARTBELlfdnr { get; private set; }

    public POSViewHolder(View itemView) : base(itemView)
    {
        ...

        ARTminus.Click += OnMinusClick;
        Artplus.Click += OnPlusClick;
    }

    private void OnMinusClick(object s, EventArgs e)
    {
        MinusClick?.Invoke(this, EventArgs.Empty);
    }

    private void OnPlusClick(object s, EventArgs e)
    {
        PlusClick?.Invoke(this, EventArgs.Empty);
    }
}

然后在你的 Adapter 中绑定 ViewHolder:

var vh = holder as POSViewHolder;
vh.MinusClick += MinusClick;
vh.PlusClick += PlusClick;

private void MinusClick(object sender, EventArgs e)
{
    if (sender is RecyclerView.ViewHolder holder)
    {
        var position = holder.AdapterPosition;
        // do other stuff...
    }
}