C# ListView筛选器。。不遵循过滤器的图像

C# ListView筛选器。。不遵循过滤器的图像,c#,android,filter,mono,android-listview,C#,Android,Filter,Mono,Android Listview,我已经为我的listview创建了一个自定义适配器,它可以扩展自定义视图,并允许用户过滤列表 这一切都很好,但问题是我在listview项目中放置的图标没有跟随过滤后的数据 例子 注意图标不会改变位置,但名称已正确过滤。 这是我的自定义适配器,它完成了自定义listview 我使用的是Mono,所以它是用C#编写的,但希望你们java的家伙也能告诉我我在这里做什么 /// <summary> /// ArrayAdapter to handle displaying student

我已经为我的listview创建了一个自定义适配器,它可以扩展自定义视图,并允许用户过滤列表

这一切都很好,但问题是我在listview项目中放置的图标没有跟随过滤后的数据

例子

注意图标不会改变位置,但名称已正确过滤。

这是我的自定义适配器,它完成了自定义listview

我使用的是Mono,所以它是用C#编写的,但希望你们java的家伙也能告诉我我在这里做什么

/// <summary>
/// ArrayAdapter to handle displaying student with risk indicator
/// </summary>
private class StudentListAdapter : ArrayAdapter<Student>
{
    private IList<Student> items;
    private Context outer_context;

    public StudentListAdapter(Context context, int resource, int textViewResourceId, IList<Student> items)
        : base(context, resource, textViewResourceId, items)
    {
        this.items = items;
        this.outer_context = context;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater vi = (LayoutInflater)outer_context.GetSystemService(Context.LayoutInflaterService);
        View tmpView = vi.Inflate(Resource.Layout.ItemStudent, null);

        // call base.GetView that uses Object.ToString() to keep sorting intact
        View v = base.GetView(position, tmpView, parent);

        Student s = items[position];
        if (s != null)
        {
            // determine correct risk image
            ImageView listRisk = v.FindViewById<ImageView>(Resource.Id.listRisk);
            if (s.R != null)
            {
                switch ((int)s.R.Value)
                {
                    case 1:
                        listRisk.SetImageResource(Resource.Drawable.risk_green);
                        break;
                    case 0:
                        listRisk.SetImageResource(Resource.Drawable.risk_yellow);
                        break;
                    case -1:
                        listRisk.SetImageResource(Resource.Drawable.risk_red);
                        break;
                    case -2:
                        listRisk.SetImageResource(Resource.Drawable.risk_red2);
                        break;
                    default:
                        listRisk.SetImageResource(Resource.Drawable.risk_gray);
                        break;
                }
            }
            else
            {
                listRisk.SetImageResource(Resource.Drawable.risk_gray);
            }
        }

        return v;
    }
}
//
///ArrayAdapter用于处理显示带有风险指示器的学生
/// 
私有类StudentListAdapter:ArrayAdapter
{
私人物品;
私人语境与外部语境;
public StudentListAdapter(上下文上下文、int-resource、int-textViewResourceId、IList项)
:base(上下文、资源、textViewResourceId、项目)
{
这个项目=项目;
this.outer_context=上下文;
}
公共覆盖视图GetView(int位置、视图转换视图、视图组父视图)
{
LayoutInflater vi=(LayoutInflater)外部上下文.GetSystemService(context.LayoutInflaterService);
查看tmpView=vi.Inflate(Resource.Layout.itemstustudent,null);
//调用base.GetView,该视图使用Object.ToString()保持排序完整
视图v=base.GetView(位置、tmpView、父视图);
学生s=项目[职位];
如果(s!=null)
{
//确定正确的风险形象
ImageView listRisk=v.FindViewById(Resource.Id.listRisk);
如果(s.R!=null)
{
开关((int)s.R.值)
{
案例1:
listRisk.SetImageResource(Resource.Drawable.risk_绿色);
打破
案例0:
listRisk.SetImageResource(Resource.Drawable.risk_-yellow);
打破
案例1:
listRisk.SetImageResource(Resource.Drawable.risk_red);
打破
案例2:
listRisk.SetImageResource(Resource.Drawable.risk_red2);
打破
违约:
listRisk.SetImageResource(Resource.Drawable.risk_gray);
打破
}
}
其他的
{
listRisk.SetImageResource(Resource.Drawable.risk_gray);
}
}
返回v;
}
}
更新

经过一些断点和检查,我发现当列表过滤时,它在过滤之前重建整个列表

例如,当在筛选字段中键入字母时,通过GetView()进程运行的第一个学生(
s
)是列表中的第一个学生
Heath,Ackerson
,即使过滤器与他不匹配也是如此

因此,似乎过滤是在运行GetView之后进行的,将图像保留在原位。。。还是不知道怎么修

*完整解决方案*


尝试实例化
ImageView listRisk=v.FindViewById(Resource.Id.listRisk)
,然后在每种情况下设置资源。

检查tmpView和v。我没有Mono的东西,所以我不能看ArrayAdapter的实现

我看到了这个问题的出现,因为我的观点最终在我做人口统计之前就被添加到了父视图中。GetView()的默认实现将视图添加到父视图并返回父视图,而不是新膨胀的视图。在父对象上执行findViewById()时,总是返回相同的ImageView(可能是列表中的第一个),而不是我新扩展的视图中的ImageView

如果是这种情况,请不要将parent传递给base.GetView(),而是传递null。在GetView()实现的末尾,将新膨胀的视图添加到父视图中。

我注意到的一件事(在使用Java而不是Mono进行编码时)是,如果您尝试这样做:

imageView.setImageResource(R.myResourceID1);
imageView.setImageResource(R.myResourceID2);
显示的图像将始终为myResourceID1。为了解决这个问题,我的同事建议在您想要设置已设置的imageView资源时使用此代码。因此:

imageView.setImageResource(R.myResourceID1);
imageView.setImageResource(0);  //supposedly invalidates the image resource
imageView.setImageResource(R.myResourceID2);
虽然在阅读更新之后,如果在getView()方法中设置ImageView之后进行过滤,这可能不是您的问题。我想与大家分享一下,因为通过getView()第二次设置已经使用过的imageView的资源听起来像是我上面描述的问题。

我将执行以下操作: 在布局中放置EditText和ListView。 使用BaseAdapter而不是ArrayAdapter。实际上是一样的,但我不调用base.getView():

私有类StudentListAdapter:BaseAdapter
{
私人物品;
私人语境与外部语境;
public StudentListAdapter(上下文,IList项)
{
这个项目=项目;
this.outer_context=上下文;
}
公共覆盖视图GetView(int位置、视图转换视图、视图组父视图)
{
LayoutInflater vi=(LayoutInflater)外部上下文.GetSystemService(context.LayoutInflaterService);
视图v=vi.Inflate(Resource.Layout.itemstustudent,null);
学生s=项目[职位];
v、 findviewbyd(R.id.text\u view\u id).setText(s.Name);
//确定正确的风险形象
ImageView listRisk=v.FindViewById(Resource.Id.listRisk);
如果(s.R!=null)
{
开关((int)s.R.值)
{
案例1:
listRisk.SetImageResource(Resource.Drawable.risk_绿色);
打破
案例0:
listRisk.SetImageResource(Resource.Drawable.risk_-yellow);
打破
案例1:
listRisk.SetImageResource(
private class StudentListAdapter : BaseAdapter
{
    private IList<Student> items;
    private Context outer_context;

    public StudentListAdapter(Context context, IList<Student> items)
    {
        this.items = items;
        this.outer_context = context;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater vi = (LayoutInflater)outer_context.GetSystemService(Context.LayoutInflaterService);
        View v = vi.Inflate(Resource.Layout.ItemStudent, null);

        Student s = items[position];

        v.FindViewById<TextView>(R.id.text_view_id).setText(s.Name);

        // determine correct risk image
        ImageView listRisk = v.FindViewById<ImageView>(Resource.Id.listRisk);
        if (s.R != null)
        {
            switch ((int)s.R.Value)
            {
                case 1:
                    listRisk.SetImageResource(Resource.Drawable.risk_green);
                    break;
                case 0:
                    listRisk.SetImageResource(Resource.Drawable.risk_yellow);
                    break;
                case -1:
                    listRisk.SetImageResource(Resource.Drawable.risk_red);
                    break;
                case -2:
                    listRisk.SetImageResource(Resource.Drawable.risk_red2);
                    break;
                default:
                    listRisk.SetImageResource(Resource.Drawable.risk_gray);
                    break;
            }
        }
        else
        {
            listRisk.SetImageResource(Resource.Drawable.risk_gray);
        }

        return v;
    }

    void displayNewData(IList<Student> new_items)
    {
        items=new_items;
        notifyDatasetChanged();
    }
}
public class StudentsActivity extends Activity {

    public override void onCreate(Bundle savedInstanceState) 
    {
        ...
        filterEditText.addTextChangedListener(filterTextWatcher);
    }

    private TextWatcher filterTextWatcher = new TextWatcher() 
    {

        public void afterTextChanged(Editable s) {}
        public void beforeTextChanged(CharSequence s, int start, int count,int after) {}

        public void onTextChanged(CharSequence filter, int start, int before, int count) 
        {
            IList<Student> items = getStudentsFiltered(filter);
            adapter.displayNewData(items);
        }
    };

    //getStudentsFiltered() method may look like that:
    getStudentsFiltered(String filter)
    {
        IList<Student> students_filtered=new List<Students>();
        foreach(Student student in students)
        if(student.Name.Contains(filter))
                students_filtered.Add(student);
        return students_filtered;
    }
}