0
public new int VirtualListSize
    {
        get { return base.VirtualListSize; }
        set
        {
            // If the new size is smaller than the Index of TopItem, we need to make
            // sure the new TopItem is set to something smaller.
            if (VirtualMode &&
                View == View.Details &&
                TopItem != null &&
                value > 0 &&
                TopItem.Index > value - 1)
            {
                TopItem = Items[value - 1];
            }

            base.VirtualListSize = value;
        }
    }

我正在尝试设置 listview 的 topitem 属性,但是在虚拟模式下,项目被禁用。所以任何试图在虚拟模式下访问它的代码都会抛出一个无效操作异常。当我尝试逐行调试时不会发生异常。如果我评论该行TopItem=Items[value-1],它不会引发任何异常。

System.InvalidOperationException:在 VirtualMode 中,ListView RetrieveVirtualListItem 事件需要每个 ListView 列的列表视图 SubItem。在 System.Windows.Forms.ListView.WmReflectNotify(Message& m) 在 System.Windows.Forms.ListView.WndProc(Message& m) 在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam ) 请建议。

4

1 回答 1

4

TopItem当虚拟列表大小变小时,您不需要更改。.NETListView已经这样做了。根据 dotPeek 反汇编程序:

public int VirtualListSize { 
    ... 
    set {
        ...
        bool keepTopItem = this.IsHandleCreated && VirtualMode && this.View == View.Details && !this.DesignMode; 
        int topIndex = -1;
        if (keepTopItem) { 
            topIndex = unchecked( (int) (long)SendMessage(NativeMethods.LVM_GETTOPINDEX, 0, 0)); 
        }

        virtualListSize = value;

        if (IsHandleCreated && VirtualMode && !DesignMode)
            SendMessage(NativeMethods.LVM_SETITEMCOUNT, virtualListSize, 0); 

        if (keepTopItem) { 
            topIndex = Math.Min(topIndex, this.VirtualListSize - 1); 
            // After setting the virtual list size ComCtl makes the first item the top item.
            // So we set the top item only if it wasn't the first item to begin with. 
            if (topIndex > 0) {
                ListViewItem lvItem = this.Items[topIndex];
                this.TopItem = lvItem;
            } 
        }
    } 
}

这个问题在于,根据我的经验,TopItem在虚拟列表视图上进行设置是一个容易出错的活动。在我的代码中,我有这个块:

// Damn this is a pain! There are cases where this can also throw exceptions!
try {
    this.listview.TopItem = lvi;
}
catch (Exception) {
    // Ignore any failures
}

由于设置TopItem有时会引发异常,这意味着有时设置VirtualListSize同样会引发异常。

其他要点

即使在虚拟模式下,您也可以Items通过索引访问集合。所以,这很好(假设列表不为空):

this.listview1.TopItem = this.listview1.Items[this.listview1.Items.Count - 1];

不能Items在虚拟模式下迭代集合。这将引发异常:

foreach (ListViewItem item in this.listview1.Items) { ... }
于 2015-02-10T05:39:18.547 回答