加载时Listview太慢了

时间:2013-10-29 12:59:01

标签: c# winforms listview

我正在使用1286条记录填充列表视图,大约需要34秒。我在网上搜索,发现了这个

 private void PopulateListViewWithCables(List<Cable> cables)
    {
        listView1.BeginUpdate();
        listView1.Items.Clear();
        System.Diagnostics.Stopwatch myStopWatch = new System.Diagnostics.Stopwatch();
        myStopWatch.Start(); 
        AddItemsToListView(cables);
        myStopWatch.Stop();
        string str;
        str = myStopWatch.Elapsed.Seconds.ToString();
        string s = str;
        listView1.EndUpdate();
    }


    private void AddItemsToListView(List<Cable> cables)
    {
        //Add to an ArrayList first because AddRange is a lot faster
        //than Add when dealing with lots of elements.
        //Also, there is no need to turn off the sorter when adding
        //all the elements at once

        ArrayList listItems = new ArrayList();

        foreach (Cable cable in cables)
        {
            // The if statement can be removed if all items in
            // MyDataClassCollection should be added to the ListView.               
            listItems.Add(CreateListViewItem(GetCableNavigation(cable)));
        }

        // Adds the items to the ListView
        listView1.Items.AddRange(
        (ListViewItem[])listItems.ToArray(typeof(ListViewItem)));
    }

    // Generate a listviewitem by using the myDataItem instance.
    private static ListViewItem CreateListViewItem(Cable cable)
    {
        ListViewItem item = new ListViewItem(
        new string[]
    {
    cable.Id.ToString(),
       cable.Item.ToString(),
       cable.GeneralFormat + cable.TagNo.ToString() + cable.EndString,
       cable.FromBay + cable.FromPanel, 
       cable.ToBay + cable.ToPanel,
       cable.CableProperty.Catalogue.Type,
       cable.CableProperty.Catalogue.CoreSize,
       cable.CableProperty.CableApplication.Application, 
       cable.CableRevision,
       cable.MinRequestCore.ToString(), 
       cable.Route, 
       cable.Distance.ToString(),
       ((CableStatusEnum)cable.Status).ToString(),
       cable.CableProperty.ProjectId.ToString(), 
       cable.CablePropertyId.ToString(),
       cable.TagNo.ToString(), 
       cable.GeneralFormat,
       cable.Length.ToString(), 
       cable.EndString, 
       cable.User.LastName, 
       cable.EditedOn.ToString()                
   });          
        return item;
    }

   private Cable GetCableNavigation(Cable cable)
    {
        CurrentInfo currentInfo = CurrentInfo.RecGetSingle();
        if (cable.CableProperty == null || cable.User == null)
        {
            using (CableServiceClient client = new CableServiceClient())
            {
                SearchElement[] criteria = new SearchElement[] { new SearchElement { Comparison = "=", FieldName = "Id", FieldValue = cable.Id, LogicalOperator = "" } };
                cable = client.GetCables(criteria, null, "CableProperty,CableProperty.Catalogue,CableProperty.CableApplication,User").SingleOrDefault();
                client.Close();
            }
        }
        return cable;
    }

我可以将加载时间减少到29秒,但对于1286条记录仍然太多,我怎样才能减少加载数据的时间?

谢谢

3 个答案:

答案 0 :(得分:2)

我认为您的代码大部分时间都在创建服务客户端并从中查询数据。我建议你拆分数据加载(你可以在后台线程中进行)和数据显示操作。还要考虑重新使用单个服务客户端实例。

类似的东西:

private void AddItemsToListView(List<Cable> cables)
{
    var items = GetCableNaviagations(cables)
                   .Select(CreateListViewItem)                       
                   .ToArray();

    listView1.Items.AddRange(items);
}

// consider to do data retrieving in background thread
private IEnumerable<Cable> GetCableNaviagations(IEnumerable<Cable> cables)
{
   var arg = "CableProperty,CableProperty.Catalogue,CableProperty.CableApplication,User";

   using (CableServiceClient client = new CableServiceClient())
   {
        foreach(var cable in cables)
        {
           var criteria = new SearchElement[] { 
              new SearchElement { 
                   Comparison = "=", 
                   FieldName = "Id", 
                   FieldValue = cable.Id, 
                   LogicalOperator = ""      
              } };

           yield return client.GetCables(criteria, null, arg).SingleOrDefault();
        }

        client.Close();
    }
}

答案 1 :(得分:2)

假设这是System.Windows.Forms.ListView,您应该看一下virtualization。使用虚拟化将自动为您执行延迟加载listview项目,从而减少内存使用量并缩短响应时间。

答案 2 :(得分:0)

它不会改变数据检索的时间,但可以帮助列表视图的“加载”阶段。创建一个返回“ListViewItem []”的方法并使用Yield return:

private void PopulateListViewWithCables(List<Cable> cables)
{
    listView1.BeginUpdate();
    listView1.Items.Clear();
    System.Diagnostics.Stopwatch myStopWatch = new System.Diagnostics.Stopwatch();
    myStopWatch.Start();         
    foreach (listitem i in AddItemsToListView(cables))
    {
            cables.Add(i);
    }
    AddItemsToListView(cables);
    myStopWatch.Stop();
    string str;
    str = myStopWatch.Elapsed.Seconds.ToString();
    string s = str;
    listView1.EndUpdate();
}


private IEnumerable<ListViewItem> AddItemsToListView(List<Cable> cables)
{
    foreach (Cable cable in cables)
    {        
        yield return(CreateListViewItem(GetCableNavigation(cable)));
    }

}

我写了它而没有检查它是否编译。