C# 按钮单击可绑定到自定义列表视图中的多个视图

C# 按钮单击可绑定到自定义列表视图中的多个视图,c#,android,xamarin.android,C#,Android,Xamarin.android,我正在为列表视图使用自定义列表适配器。我已经在列表视图中定义了一个按钮,单击事件可以工作,但问题是一旦列表被滚动,它就会用同一个按钮绑定多个视图。因此,单击按钮后,将触发与每个关联视图关联的事件 如何处理这个问题?我想您可能误解了列表的工作原理,尤其是convertView的使用方式 Android中的ListView虚拟化UI——就像WP中的ListBox和iOS中的UITableView一样 这意味着,如果基础列表有1000个项目,但屏幕上只有容纳10个项目的空间,那么列表将只创建10个“容

我正在为列表视图使用自定义列表适配器。我已经在列表视图中定义了一个按钮,单击事件可以工作,但问题是一旦列表被滚动,它就会用同一个按钮绑定多个视图。因此,单击按钮后,将触发与每个关联视图关联的事件


如何处理这个问题?

我想您可能误解了列表的工作原理,尤其是convertView的使用方式

Android中的ListView虚拟化UI——就像WP中的ListBox和iOS中的UITableView一样

这意味着,如果基础列表有1000个项目,但屏幕上只有容纳10个项目的空间,那么列表将只创建10个“容器”来显示列表项目,并使用这些容器仅显示当时正在查看的内容

它这样做的方式是通过适配器,特别是通过GetView回调,它将convertView作为其参数之一

如果选择在GetView实现中创建新视图,则可以在回调中订阅新事件

相反,如果您选择在GetView实现中使用convertView,那么您不应该在回调中订阅新事件,除非先取消订阅旧事件

e、 g.我猜你的代码目前做的是这样的:

 public View GetView(int pos, View convertView)
 {
     TextView toShow = convertView as TextView;
     if (toShow == null)
     {
        toShow = new TextView();
     }

     toShow.Text = "Item at position " + i;
     toShow.Click += (s,e) => {
         // do something
     };

     return toShow;
 }
代码的问题是,您将订阅过多的单击。。。您需要通过以下方式解决此问题:

 public View GetView(int pos, View convertView)
 {
     TextView toShow = convertView as TextView;
     if (toShow == null)
     {
        toShow = new TextView();
        toShow.Click += (s,e) => {
            // do something with the position embedded in toShow.Tag
        };
     }

     toShow.Text = "Item at position " + i;
     toShow.Tag = new WrappedPosition(i);
     return toShow;
 }

这是我的猜测:)

斯图尔特完全正确-问题是ListView中的视图被重用(以避免创建不同的对象),并且由于列表的不同部分是可见的,对于一个新位置,您可以获得不再使用的任何视图。因此,您的代码应该正确处理此问题。 我想补充一点,monodroid中Java对象的垃圾收集效果不好。根据我的经验,创建大量从Java.Lang.Object派生的对象会使应用程序崩溃。因此:

  • 为每一新行创建新视图将很快使应用程序崩溃,因此您必须尽可能重用convertView

  • 标记的类型为Java.Lang.Object,因此WrappedPosition应该派生自Java对象。这意味着,您应该重用同一个实例,而不是每次都创建新实例

  • 如果您将点击处理程序移动到一个单独的方法,您可以在订阅之前取消订阅,所以您不需要任何逻辑“If view is null”


  • 如果您觉得它有用,我可以在这里发布一个代码示例来解释它是如何工作的。不要一开始就发布它,因为它相当大:)

    显示您的代码。没有代码就无法解决:)视图=(convertView??context.LayoutInflater.Inflate(Resource.Layout.HotelCustomListItem,parent,false))作为线性布局;这基本上就是我们正在做的事情。我已经在上面提到的布局中定义了一个按钮。滚动列表时,会创建新视图,但与每个视图关联的控件似乎是相同的。