Xamarin BaseExpandableListAdapter 在按钮上的 OnClick 方法中返回错误的视图

问题描述 投票:0回答:1

我在 Xamarin 中有相同的基本可扩展列表,其中包含包含 EditText 的项目。所以基本上列表中的每个项目都有“加 1”或“减 1”以及显示值的 EditText。它基本上是一个购物车,其中有一组物品,并且在一组内您可以购买多个物品。

问题是,当我单击“添加 1”(+1) 按钮时,我会得到完全不同的视图,并且更新其他一些 EditText,而不是同一子视图中的 EditText。

public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
    {
        Holder<HolderObject> holder;
        var child = (JavaObjectWrapper<MobilePOSSubItem>)GetChild(groupPosition, childPosition);

        if (convertView == null)
        {
            convertView = context.LayoutInflater.Inflate(Resource.Layout.mobilePOSTicketsSubItem, null);
            holder = new Holder<HolderObject>(
                new HolderObject {
                    GroupPosition = groupPosition,
                    ChildPosition = childPosition,
                    Amount = convertView.FindViewById<EditText>(Resource.Id.etAmount),
                    Tariff = convertView.FindViewById<TextView>(Resource.Id.tariff),
                    Name = convertView.FindViewById<TextView>(Resource.Id.name),
                    Rule = convertView.FindViewById<TextView>(Resource.Id.rule),
                    IconAllotment = convertView.FindViewById<ImageView>(Resource.Id.iconAllotment),
                    AddButton = convertView.FindViewById<ImageButton>(Resource.Id.add),
                    RemoveButton = convertView.FindViewById<ImageButton>(Resource.Id.remove)
            });

            convertView.Tag = holder;
            convertView.SetTag(Resource.Id.etAmount, holder.Value.Amount);
            convertView.SetTag(Resource.Id.tariff, holder.Value.Tariff);
            convertView.SetTag(Resource.Id.name, holder.Value.Name);
            convertView.SetTag(Resource.Id.rule, holder.Value.Rule);
            convertView.SetTag(Resource.Id.iconAllotment, holder.Value.IconAllotment);
            convertView.SetTag(Resource.Id.add, holder.Value.AddButton);
            convertView.SetTag(Resource.Id.remove, holder.Value.RemoveButton);
        } else
        {
            holder = (Holder<HolderObject>)convertView.Tag;
            holder.Value.Amount.AfterTextChanged -= EtAmount_TextChanged;
        }

        holder.Value.Amount.SetText(child.Object.Value.ToString(), TextView.BufferType.Editable);
        holder.Value.Amount.SetSelectAllOnFocus(true);

        holder.Value.Amount.AfterTextChanged += EtAmount_TextChanged;
... 


private void EtAmount_TextChanged(object sender, AfterTextChangedEventArgs e)
    {
        if (sender.GetType().BaseType == typeof(EditText))
        {
            var etAmount = (EditText)sender;
            var parent = (View) etAmount.Parent.Parent;
            Holder<HolderObject> holder = (Holder<HolderObject>)parent.Tag;
            int value = 0;
            string newValue = e.Editable.ToString();
            try
            {
                if (!string.IsNullOrEmpty(newValue))
                {
                    value = Convert.ToUInt16(newValue);
                }
                else
                {
                    holder.Value.Amount.Text = "0";
                }

            }
            catch
            {
                holder.Value.Amount.Text = "0";
            }

            items[holder.Value.GroupPosition].SubItems[holder.Value.ChildPosition].Value = value;
            NotifyDataSetChanged();
            //UpdateSelectedItem(child, value);
        }
    }


public void OnClick(View v)
    {
        HideSoftKeyboard(listView);

        View parent = (View) v.Parent.Parent.Parent;
        HolderObject holder = ((Holder<HolderObject>)parent.Tag).Value;

        var child = (JavaObjectWrapper<MobilePOSSubItem>) GetChild(holder.GroupPosition, holder.ChildPosition);
        if (holder.Amount != null)
        {
            int value;
            if (int.TryParse(holder.Amount.Text, out value))
            {
                if (v.Id.Equals(Resource.Id.add))
                {
                    if (value < 299 && (child.Object.ValueMax == null || value < child.Object.ValueMax))
                    {
                        value++;
                        holder.Amount.Text = value.ToString();
                    }
                }
                else if (v.Id.Equals(Resource.Id.remove))
                {
                    if (value > 0 && (child.Object.ValueMin == null || value > child.Object.ValueMin))
                    {
                        value--;
                        holder.Amount.Text = value.ToString();
                    }
                }
            }
            else
            {
                holder.Amount.Text = "0";
            }
        }
        else
        {
            CultureInfo original = CultureInfo.CurrentCulture;
            NumberFormatInfo noCurrencySymbol = (NumberFormatInfo)original.NumberFormat.Clone();
            noCurrencySymbol.CurrencySymbol = string.Empty;

            var cbArticle = (CheckBox)v;
            child.Object.ArticleList.FirstOrDefault(x => x.ArticleId == cbArticle.Id).Value = (cbArticle.Checked) ? 1 : 0;
            holder.Tariff.Text = string.Format("{0} {1}", child.Object.Currency, child.Object.GetTotalAmount().ToString("C", noCurrencySymbol));
        }
    }

所以基本上我认为可行的是:

  1. 在GetChildView中,如果convertView为空,则使用布局对其进行膨胀,并使用childPosition和GroupPosition将Holder对象附加到它
  2. 在 Holder 中的 EditText 上附加 AfterTextChanged 并将 OnClick 方法附加到按钮
  3. 流程:用户点击“add 1” -> onClick 方法触发 -> 我获取按钮的父级并获取 Holder 对象 -> 我更改该 Holder 对象中 EditText 的值 -> AfterTextChanged 被触发并更新列表中的子项

如果我滚动,EditText 值将变为 0,单击按钮将获得完全不同的视图。因此,如果我单击第二组中的第二项(即基于索引的 groupPosition: 1 和 childPosition: 1),我尝试获取 Holder 对象,而 Holder 对象具有 groupPosition:0 和 childPosition:5 这是完全错误的值。

我还设置了稳定的 id,我可以确认所有孩子都有不同的 id:

public override long GetChildId(int groupPosition, int childPosition)
    {
        return (long) items[groupPosition].SubItems[childPosition].Idx;
    }
public override bool HasStableIds
    {
        get
        {
            return true;
        }
    }
android xamarin expandablelistview
1个回答
0
投票

问题是这条线

convertView.Tag = holder;
。 将支架附加到视图应该是您在函数中执行的最后一件事,因此我将该行移至函数末尾,并且一切正常,就在
return convertView
之前。错误是我首先将持有者附加到视图,然后更改它并将侦听器添加到持有者视图。这应该是最后一件事,首先将所有内容应用到持有者视图(如文本、侦听器、颜色等),最后将其附加到视图。

© www.soinside.com 2019 - 2024. All rights reserved.