从GetView()方法中的同一ListView行的列表中返回重复值的最佳方法是什么?

时间:2017-12-08 19:38:39

标签: c# android listview

我在列表中有一些数据,例如显示订单的商品编号,行号,数量和包装尺寸。问题是订单上的某些行将具有相同的项目编号,但数量,包装尺寸或两者都不同。例如:

Order#  Line#   Item#   Qty    Pack Size
100      1      12345   640     (10@64)
100      1      12345   128     (1@128)
100      2      23124    48     (1@48)
100      3      53425    80     (1@80)

上面显示的项目12345他们总共订购了768件,但是对于这些件中的640件,他们希望收到10件装,每件64件,他们希望只有一件装有128件。自然创建ListView时,它将为列表中的每一行创建4行,一行。我希望每个Item#只显示3行,如果有重复项,则应添加数量并将包大小合并为一行。我尝试过这样的事情,试图强迫它做我想做的事,但显然效果不好。我对Android和ListView相当新,所以我希望有更好的方法来实现这一点。有人能指出我正确的方向吗?

    public class LoadInfoViewAdapter : BaseAdapter<Items>
{
    private List<Items> lItems;
    private Context gContext;
    private string gLoadnStop;
    private string gPacks;
    private decimal gtotal;
    int total;

    public LoadInfoViewAdapter(Context context, List<Items> loadinfo,  string LoadnStop)
    {
        lItems = loadinfo;
        gContext = context;
        gLoadnStop = LoadnStop;

    }

    public override int Count
    {
        get { return lItems.Count; }
    }
    public override long GetItemId(int position)
    {
        return position;
    }
    public override Items this[int position]
    {
        get { return lItems[position]; }
    }
    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        if (row == null)
        {
            row = LayoutInflater.From(gContext).Inflate(Resource.Layout.LoadInfoItems_Row, null);
        }
        //If the item at the current position is the same as the item in the next position add the qty and combine the packs
        if (lItems[position].ItemNo == lItems[position + 1].ItemNo)
        {
            string itemno = lItems[position].ItemNo;
            int count = 0;
            row.FindViewById<TextView>(Resource.Id.txtItemNo).Text = lItems[position].ItemNo.Trim();
            row.FindViewById<TextView>(Resource.Id.txtLineNo).Text = lItems[position].LineNum.Trim();
            foreach (var item in lItems.Where(r => r.ItemNo == itemno))
            {
                if (count == 0)
                {
                    gPacks = lItems[position].Pack.ToString().Trim();
                    gtotal = lItems[position].Qty;
                }
                else
                {
                    gPacks = lItems[position + 1].Pack.ToString().Trim() + ", " + gPacks;
                    gtotal = lItems[position + 1].Qty + gtotal;
                }
                count = +1;
            }
            row.FindViewById<TextView>(Resource.Id.txtQuantity).Text = gtotal + " (" + gPacks + ") ";
            gtotal = 0;
        }
        //check to see if the current item is was the same as the previous item added.  If so I dont want to create a row for that item.
        else if (lItems[position].ItemNo == lItems[position - 1].ItemNo)
        {
            //Not too sure what would be the best code to go here
        }
        //if it has no duplicate create the row like normal
        else
        {
            row.FindViewById<TextView>(Resource.Id.txtItemNo).Text = lItems[position].ItemNo.Trim();
            row.FindViewById<TextView>(Resource.Id.txtLineNo).Text = lItems[position].LineNum.Trim();
            row.FindViewById<TextView>(Resource.Id.txtQuantity).Text = lItems[position].Qty.ToString().Trim() + lItems[position].Pack.ToString().Trim();
        }
        return row;
    }

我希望它能返回这样的东西:

12345  1   768((10@64),(1@128))
23124  2   48(1@48)
53425  3   80(1@80)

无论出于何种原因,它会做我希望重复的项目编号,但它有时会复制列表中的不同项目,如:

12345  1   768((10@64),(1@128))
23124  2   48(1@48)
53425  3   80(1@80)
23124  2   48(1@48)

有人有任何建议吗?

1 个答案:

答案 0 :(得分:0)

您的根本问题是,商品索引器声明您有4个商品可用,但您想要的结果是3个商品。

这不是您应该在BaseAdapter中解决的任务。您应该提前处理列表,并在将其传递到基础适配器之前减少到目标3项。

此外,您应该尽量避免在GetView中使用FindViewFromId,除非convertView为null。为此,您可以将之前标识的视图打包到Tag属性中:这就是它的用途,请参阅https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/

如果你真的想在基础适配器中完成所有操作,那么转换构造函数中的项目,如下所示:

public class LoadInfoViewAdapter : BaseAdapter<Items>
{
    private List<CondensedItems> cItems;
    private Context gContext;

    public LoadInfoViewAdapter(Context context, List<Items> loadinfo,  string LoadnStop)
    {        
        gContext = context;
        gLoadnStop = LoadnStop;

        // Get all of the unique item numbers.
        var uniqueItemNos = loadInfo.Select(x => x.ItemNo).Distinct();

        cItems = new List<CondensedItem>();

        foreach(string uniqueItem in uniqueItemNos)
        {
            // Gets all of the items with the target itemNo.  If you want to avoid merging them all, you need to do some work checking for sequential indexes or something similar.
            var matchingItems = loadInfo.Select(x => x.ItemNo == uniqueItem).ToList();
            var lineNo = matchingItems[0].LineNo;
            var qty = matchingItems.Sum(x => x.Qty).ToString();

            StringBuilder packsSB = new StringBuilder();

            foreach(var item in matchingItems)
            {
                packs.Append(item.Pack + ",");
            }

            string packs = packsSB.ToString().Trim(',');

            cItems.Add(
                new CondensedItem 
                {
                    ItemNo = uniqueItem,
                    LineNo = lineNo,
                    Packs = $"{qty}({packs})"
                });  
        }       
    }

    public override int Count
    {
        get { return cItems.Count; }
    }
    public override long GetItemId(int position)
    {
        return position;
    }
    public override Items this[int position]
    {
        get { return cItems[position]; }
    }
    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        CondensedViewHolder viewHolder;

        if (row == null)
        {
            row = LayoutInflater.From(gContext).Inflate(Resource.Layout.LoadInfoItems_Row, null);

            viewHolder = new CondensedViewHolder 
            {
                ItemView = row.FindViewById<TextView>(Resource.Id.txtItemNo),
                LineView = row.FindViewById<TextView>(Resource.Id.txtLineNo),
                PacksView = row.FindViewById<TextView>(Resource.Id.txtQuantity)
            }

            row.Tag = viewHolder;
        }
        else
        {
            viewHolder = row.Tag as CondensedViewHolder;
        }

        viewHolder.ItemView.Text = cItems[position].ItemNo;
        viewHolder.LineView.Text = cItems[position].LineNo;
        viewHolder.PacksView.Text = cItems[position].Packs;

        return row;
    }

    private class CondensedItem
    {
        string ItemNo { get; set; }
        string LineNo { get; set; }
        string Packs { get; set; }
    }   

    private class CondensedViewHolder : Java.Lang.Object
    {
        public TextView ItemView { get; set; }
        public TextView LineView { get; set; }
        public TextView PacksView { get; set; }
    }
}