使用文本框搜索listview项目

时间:2013-12-03 01:24:23

标签: c# listview search

我正在使用C#中的简单应用程序(电话簿),在我的项目中,我有一个填充了联系人的列表视图。我一直在努力实现使用文本框自动(即时)搜索列表视图的可能性。我已经设法使它工作,但不是以理想的方式。如果我给你举个例子,你会意识到实际的问题。假设我有一个名为比尔盖茨的联系人,当我尝试搜索它时,它会被找到并且该部分没问题。但是,问题是当我尝试搜索另一个联系人时。在这种情况下,我必须在键入其他名称之前清除文本框,但是可以只删除字母。当我开始删除整个名字时,在删除第一个字母后,它就像我刚刚输入的名字一样 - 它选择了项目(并且也集中了) - 实际上没有时间在它再次找到联系人之前删除整个名称。我必须删除第一个字母,然后切换回文本框,删除另一个字母等。是否有任何搜索自动解决方案 - 现在,但另一方面删除(清除文本框)而不选择联系人是可能的。

看看代码:

private void txt_Search_TextChanged(object sender, System.EventArgs e)
    {
        if (txt_Search.Text != "")
        {
            foreach (ListViewItem item in listView1.Items)
            {
                if (item.Text.ToLower().Contains(txt_Search.Text.ToLower()))
                {
                    item.Selected = true;
                }
                else
                {
                    listView1.Items.Remove(item);
                }

            }
            if (listView1.SelectedItems.Count == 1)
            {
                listView1.Focus();
            }
        }
        else 
        { 
            LoadContacts();
            RefreshAll();
        }
    } 

4 个答案:

答案 0 :(得分:5)

您的代码中存在一些问题,首先在通过循环修改集合时,我们不应该使用foreach,尽管在某些情况下它似乎有效但不是真的,它肯定会很奇怪未来,让你困惑。我们应该使用for循环,并以相反的顺序循环。第二个错误的做法是将Selected设置为true,这可能会导致textBox失去焦点到listView。解决方案是我们必须使用其他方式来指示项目已被选中,例如使用BackColor代替:

private void txt_Search_TextChanged(object sender, System.EventArgs e)
{
    if (txt_Search.Text != "") {
        for(int i = listView1.Items.Count - 1; i >= 0; i--) {
            var item = listView1.Items[i];
            if (item.Text.ToLower().Contains(txt_Search.Text.ToLower())) {
                item.BackColor = SystemColors.Highlight;
                item.ForeColor = SystemColors.HighlightText;
            }
            else {
                listView1.Items.Remove(item);
            }
        }
        if (listView1.SelectedItems.Count == 1) {
            listView1.Focus();
        }
    }
    else   
        LoadContacts();
        RefreshAll();
    }
}

在用户关注ListView之后,应重置所有BackColorForeColor,我们可以处理Enter ListView事件:

//Enter event handler for listView1
private void listView1_Enter(object sender, EventArgs e){
  foreach(ListViewItem item in listView1.Items){
    item.BackColor = SystemColors.Window;
    item.ForeColor = SystemColors.WindowText;
  }
}

答案 1 :(得分:1)

修改 你最好不要使用Text_Changed,而是尝试Key_Down方法,如下所示

private void txt_Search_KeyDown(object sender, KeyEventArgs e)
{
   if (e.KeyCode == Keys.Enter) //apply your search only when pressing ENTER key
     {
       // you do your search as it was before 
       // i personally don't have suggestions here
       if (!txt_Search.AutoCompleteCustomSource.Contains(txt_Search.Text)) txt_Search.AutoCompleteCustomSource.Add(txt_Search.Text);
       //the line above will save all your searched contacts and display it in a beautiful format
     }
   else if (txt_Search.Text == "")
     {
       LoadContacts();
       RefreshAll();
     }
}

当然不要忘记设置txt_Search的属性 AutoCompleteMode = SuggestAppend AutoCompleteSource = CustomSource

答案 2 :(得分:0)

这种感觉就像一个黑客,但你可以跟踪已经输入到文本框中的文本的长度,并且只有在文本的长度大于上次调用事件时才执行搜索和聚焦逻辑。 。这样,如果有人删除了一封信,搜索和聚焦就不会发生。类似的东西:

// declare lastSearchLength as a int outside of your TextChanged delegate
if (!String.IsNullOrEmpty(txt_Search.Text) && txt_Search.Text.Length > lastSearchLength)
{
    foreach (ListViewItem item in listView1.Items)
    {
        if (item.Text.ToLower().Contains(txt_Search.Text.ToLower()))
        {
            item.Selected = true;
        }
        else
        {
            listView1.Items.Remove(item);
        }

        }
        if (listView1.SelectedItems.Count == 1)
        {
            listView1.Focus();
        }

        lastSearchLength = txt_Search.Text.Length;
    }
    else 
    { 
        LoadContacts();
        RefreshAll();
    }
}

答案 3 :(得分:-1)

每次按键都会进行回发。当页面重新加载时,它将不会保留您期望的焦点。我建议在客户端上使用JavaScript实现此功能,或使用搜索按钮而不是TextChanged事件。