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
.
一种方法是在 View
的 Tag
属性 上添加 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...
}
}
我有一个大问题(对我来说,我希望你在 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
.
一种方法是在 View
的 Tag
属性 上添加 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...
}
}