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

时间:2012-11-08 10:31:23

标签: c# android xamarin.android

我正在使用自定义列表适配器进行列表视图。我在列表视图中定义了一个按钮,并且click事件有效,但问题是滚动列表后,它会使用相同的按钮绑定多个视图。因此,在单击按钮时,将触发与每个关联视图关联的事件。

我该如何处理?

2 个答案:

答案 0 :(得分:0)

我猜你误解了列表是如何工作的 - 特别是如何使用convertView。

Android中的ListViews虚拟化UI - 就像ListBoxes在WP中一样,就像iOS中的UITableViews一样

这意味着如果基础列表有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;
 }

代码的问题在于您会经常订阅Click ...您需要使用以下内容来解决:

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

无论如何,这是我的猜测:)。

答案 1 :(得分:0)

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

  1. 为每个新行创建新视图很快就会使应用程序崩溃,因此您必须尽可能重用convertView。

  2. Tag的类型为Java.Lang.Object,因此WrappedPosition应该从Java对象派生。这意味着您不应每次都创建新实例,而应重用相同的实例。

  3. 如果您将点击处理程序移动到单独的方法,您可以在订阅之前取消订阅,因此您不需要任何逻辑"如果视图为空"。

  4. 如果您觉得它很有用,我可以在这里发布解释其工作原理的代码示例。 Dodn最初发布它是因为它非常大:)