【问题标题】:c# lazy load of items in listView when search for items inside of listViewc#在listView中搜索项目时延迟加载listView中的项目
【发布时间】:2018-10-02 07:40:06
【问题描述】:

我正在尝试在 listView 中进行搜索。我尝试了两种方法,第一种是从 listView 中搜索,第二种方法是从数据库中搜索,然后用已建立的项目填充列表。我可以看到两种方式都有很长的时间来加载只有 30 条记录。我在许多教程中看到,即使在数据库或 listView 中有许多记录,它也可以快速工作并且没有任何负载。我发现在第二个示例中,当我在 listView 本身内部进行搜索时,这会出现一个问题LoadAll();,因为在每个键入的字母或数字之后,它会再次填充列表并减慢应用程序的速度。有没有什么方法可以让它工作而无需长时间加载或任何最简单的方法来做到这一点?

第一个在数据库中搜索的示例

    private void usersSearch_TextChanged(object sender, EventArgs e)
    {
        if (usersSearch.Text != "")
        {
            searchUsers(usersSearch.Text.ToLower());
        }
    }

    private void searchUsers(string searchTerm)
    {
        usersList.Items.Clear();

        string conn = ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString;
        dbConn = new MySqlConnection(conn);

        string query = "SELECT id, email, username, password FROM " +
            "users WHERE id LIKE '%" + searchTerm + "%' OR email LIKE '%" + searchTerm + "%' OR username LIKE '%" + searchTerm + "%'";

        MySqlCommand cmd = new MySqlCommand(query, dbConn);

        dbConn.Open();

        MySqlDataReader reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            ListViewItem item = new ListViewItem(new string[] { reader["id"].ToString(), reader["email"].ToString(), reader["username"].ToString(), reader["password"].ToString()});

            usersList.Items.Add(item);
        }

        reader.Close();
        dbConn.Close();
    }

在 listView 项目中搜索的第二个示例

    private void usersSearch_TextChanged(object sender, EventArgs e)
    {
        LoadAll(); // loads all data in list

        if (usersSearch.Text != "")
        {
            foreach (ListViewItem item in usersList.Items)
            {
                bool founded = false;

                string value0 = item.SubItems[0].Text;
                string value1 = item.SubItems[1].Text;
                string value2 = item.SubItems[2].Text;

                if (value0.ToLower().Contains(usersSearch.Text.ToLower()))
                {
                    item.Selected = true;
                    founded = true;
                }
                else if (value1.ToLower().Contains(usersSearch.Text.ToLower()))
                {
                    item.Selected = true;
                    founded = true;
                }
                else if (value2.ToLower().Contains(usersSearch.Text.ToLower()))
                {
                    item.Selected = true;
                    founded = true;
                }

                if (!founded) usersList.Items.Remove(item);
            }
        }
    }

【问题讨论】:

  • 如果您为用户键入的每个字符访问数据库,总会有性能成本。
  • 你不能只获取一次值并将其保存在数组/列表变量中。然后从本地列表中查找,而不是每次都调用DB?
  • 你在使用 DisplayMember 和 ValueMember 属性吗?
  • 如果您真的想更改每个字符的结果列表,请使用第二种方法,但首先加载所有记录一次,而不是一直加载。然后保留该列表(不要从中删除内容)。使用 second 列表进行显示。要获得第二个列表,请不要一直使用ToLower。或者根本没有。试试var secondList = new List<ListViewItem>(); foreach(var item in usersList.Items) { for(var i = 0; i < 3; i++) { if (item.SubItems[i].Text.IndexOf(usersSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0) { secondList.Add(item); break; } } }

标签: c# listview


【解决方案1】:

如果 - 对于您在 TextBox 中键入的每个字符 - 您将进行数据库查询以获取匹配的“建议”,这将非常缓慢。为了有效地设计这个,您必须做出几个决定(根据使用情况)。

  1. 而不是每个字符 - 仅当用户输入具有“最小”长度时才转到数据库。说 3 个左右的字符。

  2. 如果您需要执行“自动完成”的数据库/RecordSet 不是庞大且从未增长 - 您能否在应用程序加载/启动期间缓存它们。

  3. 如果记录集不断增长并且您需要它是真实的/实时的。不能虚拟化吗?即仅获取前 5 或 10 个建议,而不是全部。

【讨论】:

    【解决方案2】:

    我建议首先在列表视图中加载所有数据(在加载页面时)。 当用户在列表视图中搜索时,它应该只从现有数据中选择匹配项(列表视图已经可用)

    【讨论】:

    • 我只需要使用与搜索框中的字符串匹配的结果更新 listView 并只显示它们,而不是选择创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多