在c#win表单中,如何滚动数百个项目

在c#win表单中,如何滚动数百个项目,c#,winforms,C#,Winforms,是否存在允许用户在windows窗体容器中滚动数百或数千项的通用设计?示例:编写电子邮件客户端时,用户会感觉到在10000条消息“行”上平滑滚动,每封电子邮件一行,但这些消息在显示之前肯定不会真正呈现出来。类似地,在一个巨大的图像上滚动必须需要将其平铺成更小的部分,但是呈现该图像的代码是如何组织的?正如前面提到的可能是最好的解决方案,有一个解决方案 在表单创建时初始化虚拟模式: private void Form1_Load(object sender, EventArgs e)

是否存在允许用户在windows窗体容器中滚动数百或数千项的通用设计?示例:编写电子邮件客户端时,用户会感觉到在10000条消息“行”上平滑滚动,每封电子邮件一行,但这些消息在显示之前肯定不会真正呈现出来。类似地,在一个巨大的图像上滚动必须需要将其平铺成更小的部分,但是呈现该图像的代码是如何组织的?

正如前面提到的可能是最好的解决方案,有一个解决方案

在表单创建时初始化虚拟模式:

private void Form1_Load(object sender, EventArgs e)
        {
            listView1.VirtualMode = true;       // switching virtual mode on
            listView1.VirtualListSize = 1000000000;     // give it 1 million lines
        }
然后分配并处理
RetrieveVirtualItem
事件:

private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
   {
       ListViewItem lvi = new ListViewItem();   // create a listviewitem object
       lvi.Text = nt.MakeText(e.ItemIndex);         // assign the text to the item
       ListViewItem.ListViewSubItem lvsi = new ListViewItem.ListViewSubItem(); // subitem
       NumberFormatInfo nfi = new CultureInfo("de-DE").NumberFormat;
       nfi.NumberDecimalDigits = 0;
       lvsi.Text = e.ItemIndex.ToString("n", nfi);  // the subitem text
       lvi.SubItems.Add(lvsi);          // assign subitem to item

       e.Item = lvi;        // assign item to event argument's item-property
   } 

它是Windows设计的固有方式,不需要3个字母或特殊模式

GUI程序无论其风格如何,只要需要执行操作,都会从Windows获取消息。消息不会按其生成的顺序进行处理。有三个基本的“优先事项”:

  • 重要消息是直接传递的,底层winapi函数是SendMessage()
  • 用户输入首先存储在队列中,底层winapi函数是PostMessage()
  • 某些消息是从窗口状态合成的,仅在不需要处理上述两种消息类型时生成
消息按上述顺序处理。先发送消息,如果没有挂起消息,则程序开始清空消息队列。如果为空,则调度合成消息。绘画属于第三类。程序只有在不需要执行其他操作时才会收到WM_PAINT消息

因此,基本的事件链是,控件从消息队列中检索鼠标消息,并检测它是用于滚动条的。它计算滚动条拇指的一个新位置,并调用invalidateStuble()winapi函数来指示需要绘制窗口。函数与Winforms中的Invalidate()方法相同。内部窗口状态将更新,以标记重新绘制该矩形需要绘制。这一切都很快,没有实际的绘画发生

当程序检索下一条消息时,现在可以发生两件基本的事情。当用户不断滚动时,它可能再次是一条鼠标消息。按照与上面完全相同的方式处理,除了拇指位置的改变外,窗口不会发生任何变化

或者没有要处理的新消息,用户停止了滚动,现在类别#3合成消息得到了轮换。Windows注意到窗口需要重新绘制,并传递WM_PAINT消息


除此之外还有一些实现细节,较新版本的Windows默认启用了“拖动时显示窗口内容”系统选项。这使得用户在拖动拇指时更容易看到自己在做什么,它有意生成额外的窗口绘制。总之,操作系统和您的程序很好地支持在一个ListView中有成千上万个项目。当然不是由用户提供。

请在MSDN上查找ListView.VirtualMode属性的信息。它通过引发一个事件来管理此问题,该事件通过将项目索引到大型项目数组中来请求显示视图中的项目。问题的3个字母解决方案:。它具有内置支持、内置支持硬件加速和许多其他功能。winforms仅用于维护遗留应用程序,不建议用于任何新项目。