【问题标题】:Xamarin Recyclerview Buttons In CardView, cant get PositionCardView中的Xamarin Recyclerview按钮,无法获取位置
【发布时间】:2018-06-13 14:46:42
【问题描述】:

我有一个大问题(对我来说,我希望你在 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 中,我有我的按钮,当它们被按下时会执行 Funktion,效果不错,但我需要 CardView/Data 的位置,我正在阅读我可以通过 int position = this.RecyclerView.GetChildAdapterPosition((View)sender); 找到它,但是不工作,我不知道它是如何工作的。

【问题讨论】:

    标签: c# android xamarin android-recyclerview cardview


    【解决方案1】:

    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);
        }
    }
    

    然后在你的适配器中绑定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...
        }
    }
    

    【讨论】:

    • ok 现在可以工作了,但是我想将 mARTretourmenge 设置为 +1 或 -1,但是当我这样做时,它会得到早上 +1 或 -1 它的错误。这是在 MinusClick 中:mPOSdaten[position].mARTretourMenge = (Convert.ToInt32(mPOSdaten[position].mARTretourMenge) - 1).ToString(); NotifyItemChanged(位置);这是一个大问题,因为它必须是精确的 +1 或 -1,而且它必须每次都能正常工作而没有错误。
    • 这是一个 gif,您可以在其中看到它的效果,我认为那是因为他使用了错误的位置值。 eriappplay.de/bug.gif
    • 所以我正在调试并且位置是正确的,但他会在下一次按下时再次执行我正在执行的所有事件。所以当我按下 + 时,它会变成这个,但是当我再次按下 + 时,它会变成 2 倍
    • 解决的问题是 vh.MinusClick -= MinusClick; vh.MinusClick += 减号; vh.PlusClick -= PlusClick; vh.PlusClick += PlusClick;
    猜你喜欢
    • 2020-07-05
    • 1970-01-01
    • 2017-03-03
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多