Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows 8及更高版本短列表中包含工件的虚拟ListView_C#_Windows_Winforms_Listview_Virtual - Fatal编程技术网

C# Windows 8及更高版本短列表中包含工件的虚拟ListView

C# Windows 8及更高版本短列表中包含工件的虚拟ListView,c#,windows,winforms,listview,virtual,C#,Windows,Winforms,Listview,Virtual,我在Winform用户控件中有一个ListView。VirtualMode为true,VirtualListSize为200。当ListView中的项目少于可见行时,我会在(真实)项目下面得到奇怪的字符。当软件在Windows 8、10或Windows Server 2012上运行时,这些“工件”会出现,但在Windows 7上不会出现 有人知道是什么导致了这些“人工制品”吗?我在创建ListViewItems的所有位置的标题中添加了一个字符“a”、“B”等。所以我知道这个用户控件中没有任何代

我在Winform用户控件中有一个ListView。VirtualMode为true,VirtualListSize为200。当ListView中的项目少于可见行时,我会在(真实)项目下面得到奇怪的字符。当软件在Windows 8、10或Windows Server 2012上运行时,这些“工件”会出现,但在Windows 7上不会出现

有人知道是什么导致了这些“人工制品”吗?我在创建ListViewItems的所有位置的标题中添加了一个字符“a”、“B”等。所以我知道这个用户控件中没有任何代码在创建它们。我添加了一个示例解决方案,显示了下面的问题。 有时它们以汉字的形式出现,有时只是一个随机的字母和字符组合。通常不超过4个字符

[更新]最新版本的Windows 10上不会出现此情况


[Update2]我能够在一个小样本解决方案上重现这个问题。查找zip文件。

每当ListView中的项目数发生变化时,我都会将ListView的可见行数分配给VirtualListSize属性

我使用以下类来确定ListView中可见行的数量:

public static class ListViewSizer
{
    const UInt32 LVM_FIRST = 0x1000;
    const UInt32 LVM_GETHEADER = (LVM_FIRST + 31);

    private static int GetHeaderHeight(ListView listView)
    {
        Rect rect = new Rect();
        IntPtr hwnd = SendMessage((IntPtr)listView.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
        if (hwnd != null)
        {
            if (GetWindowRect(new System.Runtime.InteropServices.HandleRef(null, hwnd), out rect))
            {
                return rect.Bottom - rect.Top;
            }
        }

        return -1;
    }

    public static int GetLastVisibleLine(ListView listView)
    {
        int firstVisibleIndex = listView.TopItem.Index;

        int heightOfFirstItem = listView.GetItemRect(firstVisibleIndex, ItemBoundsPortion.Entire).Height;

        // assuming each item has the same height (I think this is true for list view and details view)
        const int DefaultVisibleLines = 11;
        int visibleLines = heightOfFirstItem != 0 ? (int)Math.Ceiling((decimal)((listView.Height - GetHeaderHeight(listView)) / heightOfFirstItem)) : DefaultVisibleLines;

        int lastVisibleIndexInDetailsMode = firstVisibleIndex + visibleLines;
        return lastVisibleIndexInDetailsMode;
    }

    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool GetWindowRect(System.Runtime.InteropServices.HandleRef hwnd, out Rect lpRect);

    [Serializable, System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }
}

我知道这有点像黑客。工件仍然会在那里,但是你再也看不到它们了,因为ListView总是有尽可能多的行可以显示。这是我在不更改控件的情况下所能想到的最好方法。

您的DefaultVirtualListSize不是一个好主意。避免在ListView事件的事件处理程序中分配VirtualListSize。实际上,不分配VirtualListSize会删除这些工件。但是有几页空的ListViewItems似乎也是一种奇怪的用户体验,你不觉得吗?你肯定能想出更好的方法来编写代码吗?等待事件开始查找文件是没有意义的,它会在一毫秒后触发。请记住:1)这不是我的代码。它是遗留应用程序的一部分。2) 我正在尝试修复这个错误。3) 文件的显示只是一个例子。真实的东西显示不同的对象,可能有数千个,这就是为什么选择虚拟模式。如果未初始化VirtualListSize,则不会显示任何内容。微软在他们的产品中赋予VirtualListSize更高的价值。他们说必须将VirtualListSize属性设置为虚拟列表的大小。@Hans Passant:那你为什么说DefaultVirtualListSize不是个好主意?