搜索多列ListView C#

时间:2014-07-25 20:09:11

标签: c# .net winforms listview

我有一个包含4列的ListView控件。文件名,ID,类型,项目。我通过读取包含必要字段的管道分隔文件将项目添加到ListView。一切都很好,ListView显示我的数据。但是,我想添加搜索功能,以便用户可以搜索ListView并将其过滤到仅与搜索文本匹配的项目。如果可能的话,我希望能够在键入时过滤列表。我的列表视图使用详细信息视图,其中列定义与上述4列匹配。

到目前为止,我已尝试过以下代码,但却无法弄清楚如何使其正常工作。 我的restoreAllItems方法工作正常,并恢复列表视图以包含所有项目,就好像搜索文本框为空。

这是一个获胜的表格申请

有人可以帮我指点正确的方向吗?
提前谢谢!!!

private void txtJobSearch_TextChanged(object sender, EventArgs e)
    {
        // Search items in our Jobs ListView, remove those that do not match search
        if (txtJobSearch.Text != String.Empty)
        {
            for (int i = listJobs.Items.Count - 1; i >= 0; i--)
            {                    
                if (listJobs.Items[i].Text.ToLower().Contains(txtJobSearch.Text.ToLower()))
                {
                    listJobs.Items[i].BackColor = SystemColors.Highlight;
                    listJobs.Items[i].ForeColor = SystemColors.HighlightText;
                }
                else
                {
                    for (int x = listJobs.Items[i].SubItems.Count - 1; x >= listJobs.Items[i].SubItems.Count; x--)
                    {
                        if (listJobs.Items[i].SubItems[x].Text.ToLower().Contains(txtJobSearch.Text.ToLower()))
                        {
                            listJobs.Items[i].BackColor = SystemColors.Highlight;
                            listJobs.Items[i].ForeColor = SystemColors.HighlightText;
                        }
                        else
                        {
                            listJobs.Items[i].Remove();
                        }
                    }                    
                }
            }
        }
        else
        {
            restoreAllItems("jobs");
        }
    }

3 个答案:

答案 0 :(得分:2)

我已经更新了你的代码了。由于我没有完全理解它的用途,因此删除了突出显示逻辑,但您可以轻松地将其重新置于原位。 以下代码与您的格式相同。唯一的例外是为了测试目的而实施的ReinitList()方法。

// check if current item matches search string
private bool ItemMatches(ListViewItem item, string text)
{
    bool matches = false;

    matches |= item.Text.ToLower().Contains(text.ToLower());

    if (matches)
    {
        return true;
    }

    foreach (ListViewItem.ListViewSubItem subitem in item.SubItems)
    {
        matches |= subitem.Text.ToLower().Contains(text.ToLower());
        if (matches)
        {
            return true;
        }
    }

    return false;
}

private void txtJobSearch_TextChanged(object sender, EventArgs e)
{
    // prevent flickering
    listJobs.BeginUpdate();

    // restore all items in case user deletes some characters in the textbox
    ReinitList();

    string search = txtJobSearch.Text;
    // Search items in our Jobs ListView, remove those that do not match search
    if (search != String.Empty)
    {
        for (int i = listJobs.Items.Count - 1; i >= 0; i--)
        {
            ListViewItem currentItem = listJobs.Items[i];
            if (ItemMatches(currentItem, search))
            {
                // highlight, or move highlighting to ItemMatches
            }
            else
            {
                listJobs.Items.RemoveAt(i);
            }
        }
    }

    listJobs.EndUpdate();
}


private void ReinitList()
{
    listJobs.Items.Clear();
    for (int i = 0; i < 50; i++)
    {
        ListViewItem item = new ListViewItem(i.ToString());
        item.SubItems.Add("sub " + i.ToString());
        item.SubItems.Add("sub a" + i.ToString());
        item.SubItems.Add("sub b" + i.ToString());

        listJobs.Items.Add(item);
    }
}

private void Form1_Load(object sender, EventArgs e)
{
    ReinitList();
}

答案 1 :(得分:2)

您不必再做所有这些了。它具有内置功能。它搜索所有列。

ListViewItem foundItem = listJobs.FindItemWithText(txtJobSearch.Text.ToLower());
if (foundItem != null)
{
    foundItem.BackColor = Color.Yellow;
    foundItem.Selected = true;
}

答案 2 :(得分:1)

我更改了函数以返回索引到找到的项目,但也选择并定位到视图中。这是用于化学检测和紧急响应查找的代码,这就是列表视图被命名为listViewChemical的原因。

private int ItemMatches(string text)
{
        bool matches = false;
        int idx      = -1;
        for (int i   = chemicalSearchIndex; i < listViewChemical.Items.Count; i++)
        {
            ListViewItem item = listViewChemical.Items[i];
            matches          |= item.Text.ToLower().Contains(text.ToLower());
            if (matches)
            {
                idx = item.Index;
                break;
            }
            if (!checkBoxFormulaOnly.Checked)
            {
                foreach (ListViewItem.ListViewSubItem subitem in item.SubItems)
                {
                    matches |= subitem.Text.ToLower().Contains(text.ToLower());
                    if (matches)
                    {
                        idx = item.Index;
                        break;
                    }
                }
            }
        }

        if (idx >= 0)
        {
            listViewChemical.Items[idx].EnsureVisible();
            listViewChemical.Items[idx].Selected = true;
            listViewChemical.Select();
            chemicalSearchIndex      = idx + 1;
            if (chemicalSearchIndex >= listViewChemical.Items.Count)
            {
                chemicalSearchIndex  = 0;  //go back to top
            }
        }
        else
        {
            //No matches
            chemicalSearchIndex = 0;  //set next find or next to start at the beginning of the list
        }
        return idx;
    }