简体   繁体   English

ListView在VirtualMode中时如何对ListView项进行排序?

[英]How to sort ListView items when ListView is in VirtualMode?

I realize i have to sort the collection where the ListView gathers the items from: 我意识到我必须对ListView收集项目的集合进行排序:
ListView listCollection = new ListView(); ListView listCollection = new ListView();

But this doesn't seem to work unless the ListView is added as a GUI-control to the form, that in turn makes it very slow to add items to, hence why i have to use VirtualMode on my GUI-ListView in the first place. 但是,除非将ListView作为GUI控件添加到表单中,否则这似乎不起作用,这反过来使得添加项目变得非常慢,因此我必须首先在我的GUI-ListView上使用VirtualMode 。

Anyone know how to go about this or point me in the right direction? 任何人都知道如何解决这个问题或指出我正确的方向?

basically, you will need to apply sort to the data pump itself. 基本上,您需要对数据泵本身应用排序。

I did a quick search on Google for listview sort virtualmode . 我在Google上快速搜索了listview排序虚拟模式 First result was this page , where the above quote was taken from. 第一个结果是这个页面 ,上面的引用来自。

For example, if your datasource is a DataView, apply sorting on this instead of the ListView. 例如,如果您的数据源是DataView,则对此应用排序而不是ListView。

If it is just a question of performance when adding items, I would do as barism suggests; 如果在添加物品时只是表现问题,我会像barism所说的那样做; use BeginUpdate/EndUpdate instead of VirtualMode. 使用BeginUpdate / EndUpdate而不是VirtualMode。

try {
  listView1.BeginUpdate();
  // add items
}
finally {
  listView1.EndUpdate();
}

If you are using virtual mode, you have to sort your underlying data source. 如果您使用的是虚拟模式,则必须对基础数据源进行排序。 As you may have found, ListViewItemSorter does nothing for virtual lists. 您可能已经发现,ListViewItemSorter对虚拟列表不执行任何操作。

If you are using a non-virtual listview, you can also use AddRange(), which is significantly faster than a series of Add() -- In addition to using BeginUpdate/EndUpdate that has already been described. 如果您使用的是非虚拟列表视图,则还可以使用AddRange(),它比一系列Add()快得多 - 除了使用已经描述过的BeginUpdate / EndUpdate之外。

ObjectListView (an open source wrapper around .NET WinForms ListView) already uses all these techniques to make itself fast. ObjectListView (围绕.NET WinForms ListView的开源包装器)已经使用所有这些技术来使自己快速。 It is a big improvement over a normal ListView. 它比普通的ListView有了很大的改进。 It supports both normal mode and virtual mode listviews, and make them both much easier to use. 它支持普通模式和虚拟模式列表视图,并使它们更易于使用。 For example, sorting is handled completely automatically. 例如,排序是完全自动处理的。

For very large lists, the Virtual Mode ListView is the answer for certain. 对于非常大的列表,虚拟模式ListView是肯定的答案。 In non-virtual mode it seems to draw the entire list and then clip it to the view, while in Virtual mode it simply draws the ones in the view. 在非虚拟模式下,它似乎绘制整个列表然后将其剪切到视图,而在虚拟模式下,它只是绘制视图中的那些。 In my case the list was 40K+ records. 在我的情况下,列表是40K +记录。 In non-virtual mode an update to the ListView could take minutes. 在非虚拟模式下,对ListView的更新可能需要几分钟。 In virtual mode it was instantaneous. 在虚拟模式下它是瞬间的。

To sort the list, you must sort the underlying datasource, as has already been mentioned. 要对列表进行排序,必须对基础数据源进行排序,如前所述。 That is the easy part. 这是容易的部分。 You will also need to force a refresh to the display, which is not done automatically. 您还需要强制刷新显示,而不是自动完成。 You can use ListView.TopItem.Index to find the index in the underlying data source that corresponds to the top row of the Virtual ListView before the sort. 您可以使用ListView.TopItem.Index在排序之前查找与Virtual ListView的顶行对应的基础数据源中的索引。 There is also an API call that returns the number of display rows in the ListView that you can implement as C# function, like this: 还有一个API调用,它返回ListView中可以作为C#函数实现的显示行数,如下所示:

public const Int32 LVM_GETCOUNTPERPAGE = 0x1040;

public static int GetListViewRows( ListView xoView ) 
{
   return (int)WindowsMessage.SendMessage( xoView.Handle, LVM_GETCOUNTPERPAGE, 0, 0 );
}

That will let you calculate the range you have to update. 这将让您计算您需要更新的范围。 About the only remaining question is how you reconcile the existing display with what will appear after the data have been sorted. 关于唯一剩下的问题是如何协调现有显示与数据排序显示的内容。 If you want to leave the same data element in the top row, you must have some mechanism in place that will find its new index in the newly sorted list, so you can replace it in the top position - something essentially equivalent to an SQL IDENTITY. 如果要在顶行中保留相同的数据元素,则必须有一些机制可以在新排序的列表中找到新索引,因此您可以将其替换为顶部位置 - 这基本上等同于SQL IDENTITY 。

Did you try beginupdate() and endupdate()? 你尝试过beginupdate()和endupdate()吗? Adding data is much faster when you use beginupdate/endupdate.(when you call beginupdate, listview doesn't draw until you call endupdate) 使用beginupdate / endupdate时,添加数据要快得多。(当你调用beginupdate时,listview在你调用endupdate之前不会绘制)

listView1.BeginUpdate();
for (int i = 0; i < 20000; i++)
{
listView1.Items.Add("abdc", 1);
}
listView1.EndUpdate();

I had the same problem switching VirtualMode True with an existing project, but the solution was surprisingly easy: 我在使用现有项目切换VirtualMode True时遇到了同样的问题,但解决方案非常简单:

First step I am populating a list of ListViewItem, instead of ListView.Items collection: 第一步我填充ListViewItem列表,而不是ListView.Items集合:

private List<ListViewItem> _ListViewItems;

Then I have implemented the RetrieveVirtualItem method 然后我实现了RetrieveVirtualItem方法

private void mLV_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    e.Item = _ListViewItems[e.ItemIndex];
}

Finally I am sorting my list of ListViewItem using the same class I was using before, I had just only to change the base class 最后,我使用之前使用的相同类对ListViewItem列表进行排序,我只是更改了基类

_ListViewItems.Sort((System.Collections.Generic.IComparer<ListViewItem>)new ListViewItemComparer(new int[] { e.Column }, mLV.Sorting));

This is my IComparer class implementation: 这是我的IComparer类实现:

class ListViewItemComparer : System.Collections.Generic.IComparer<ListViewItem>
{
    int[] mColonne;
    private System.Windows.Forms.SortOrder order;
    public ListViewItemComparer(int[] mCols)
    {
        this.mColonne = mCols;
        this.order = System.Windows.Forms.SortOrder.Ascending;
    }

    public ListViewItemComparer(int[] mCols, System.Windows.Forms.SortOrder order)
    {
        this.mColonne = mCols;
        this.order = order;
    }

    public int Compare(ListViewItem x, ListViewItem y)
    {
        int returnVal = -1;

        foreach (int mColonna in mColonne)
        {
            double mNum1;
            double mNum2;

            String mStr1 = "";
            String mStr2 = "";

            if ((x.SubItems[mColonna].Text == "NULL") && (x.SubItems[mColonna].ForeColor == Color.Red))
            {
                mStr1 = "-1";
            }
            else
            {
                mStr1 = x.SubItems[mColonna].Text;
            }

            if ((y.SubItems[mColonna].Text == "NULL") && (y.SubItems[mColonna].ForeColor == Color.Red))
            {
                mStr2 = "-1";
            }
            else
            {
                mStr2 = y.SubItems[mColonna].Text;
            }


            if ((double.TryParse(mStr1, out mNum1) == true) && (double.TryParse(mStr2, out mNum2) == true))
            {
                if (mNum1 == mNum2)
                {
                    returnVal = 0;
                }
                else if (mNum1 > mNum2)
                {
                    returnVal = 1;
                }
                else
                {
                    returnVal = -1;
                }
            }
            else if ((double.TryParse(mStr1, out mNum1) == true) && (double.TryParse(mStr2, out mNum2) == false))
            {
                returnVal = -1;
            }
            else if ((double.TryParse(mStr1, out mNum1) == false) && (double.TryParse(mStr2, out mNum2) == true))
            {
                returnVal = 1;
            }
            else
            {
                returnVal = String.Compare(mStr1, mStr2);
            }

            if (returnVal != 0)
            {
                break;
            }
        }

        // Determine whether the sort order is descending.
        if (order == System.Windows.Forms.SortOrder.Descending)
        {
            // Invert the value returned by String.Compare.
            returnVal *= -1;
        }
        return returnVal;
    }
}

Hope this will help you. 希望这会帮助你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#:在运行时添加项目和子项目时,VirtualMode中的ListView不显示设计时列吗? - C#: ListView in VirtualMode not displaying design-time columns when adding items & subitems at runtime? 使用ownerdraw和virtualmode在listview中闪烁 - Flickering in listview with ownerdraw and virtualmode 当所选项目不可见时,VirtualMode中的C#ListView会闪烁 - C# ListView in VirtualMode flickers when the selected item is not visible 当 Virtualmode 设置为 true 时,子项不会显示在 Listview 中 - Subitems are not shown in Listview when the Virtualmode has been set to true 在启用VirtualMode的情况下聚焦ListView中的项目 - Focus an item in ListView with VirtualMode enabled ListView [VirtualMode]更改所选索引 - ListView [VirtualMode] change selected index 对列表视图中的现有项目进行排序 - Sort existing items in listview 如何检查鼠标单击位置是否仅在虚拟模式下列表视图的Column [0]中的项目内? - How do you check if the mouse click position was only inside an item in Column[0] in a listview under virtualmode? 带有 Observablecollection 的 Listview 上的动画,在 WPF 中对项目进行排序时发生 XamlParseException - Animation on Listview with Observablecollection, XamlParseException occured when sort items in WPF 如何按列对ListView排序? - How to sort a ListView by a column?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM