从ListView派生,而不是正确绘制

时间:2010-10-29 17:20:18

标签: c# winforms listview listviewitem

我有一个常规的Forms.ListView并将其转换为虚拟列表。实现了RetrieveVirtualItem,一切正常。

然后我决定添加缓存,最后我需要排序,谁知道还有什么。由于我继承了代码并且它已经有些混乱,我决定将我的更改拉到一个单独的类中,即:从ListView派生,例如class MyOwnListView : ListView

所以我已移动它并添加了CacheVirtualItems.

在实施这两种方法后,我更换了:

private System.Windows.Forms.ListView someListView; 

private MyOwnListView someListView; 

在主表单上。

到目前为止一直这么好..但是运行,不会崩溃,但是(我现在只有大约60个项目..)当我移动滚动条时,很多都不会重新绘制,所以你'会看到空的白色行,有时它会在点击该行后重新显示/显示。我也得到部分显示和绘制的行,例如行的顶部不会完整显示。

我不确定问题是什么,我尝试添加DoubleBuffered=true; 我还在我的构造函数中添加了以下内容:(根据一些建议,我在这里找到了某个地方和/或谷歌搜索...)

SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true );
SetStyle( ControlStyles.EnableNotifyMessage, true );

和这个方法:

 protected override void OnNotifyMessage( Message m )
    {
        //Filter out the WM_ERASEBKGND message
        if ( m.Msg != 0x14 )
        {
            base.OnNotifyMessage( m );
        }
    }

我的代码整体与此非常相似:..只是为了给你一个想法:

public class MyListView: ListView
{
   private ListViewItem[] cache;
   private int firstItem;

public MyListView()
{
SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true );
SetStyle( ControlStyles.EnableNotifyMessage, true );

 RetrieveVirtualItem += new RetrieveVirtualItemEventHandler( xxx_RetrieveVirtualItem );
 CacheVirtualItems += new CacheVirtualItemsEventHandler( xxx_CacheVirtualItems );
}
 private void  xxx_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
 {
  if (cache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + cache.Length)
                e.Item = cache[e.ItemIndex - firstItem];
            else
               e.Item = GetItem(e.ItemIndex);
  }

 private void xxx_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
 {
 if (cache != null && e.StartIndex >= firstItem && e.EndIndex <= firstItem + cache.Length)
                return;

  firstItem  = e.StartIndex;
  int length = e.EndIndex - e.StartIndex + 1;
   cache = new ListViewItem[length];

   for (int i = 0; i < cache.Length; i++) 
         cache[i] = GetItem(firstItem + i);
  }

Now, GetItem, basically accesses a List<someobject>, gets the object out of list, and based on that
it creates new ListViewItem and returns it.

}

编辑:我已经为xxx_Cac​​heVirtualItems添加了一些调试代码。并且似乎每次我滚动它都会返回该项目未找到并再次将其添加到缓存中。不知道为什么。我希望在第一次滚动之后它会将它们保留在缓存中。我还在寻找。

我也尝试添加:

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);


and tried //Application.SetCompatibleTextRenderingDefault(true);

那个应用程序根本没有这些......这两行做了一些有趣的事情。 SetCompatibleTextRenderingDefault为false,根本没有滚动,而SetCompatibleTextRenderingDefault为true则滚动,但只有向下,一旦我到达底部就停止了。但屏幕上没有任何绘画/刷新问题..

1 个答案:

答案 0 :(得分:0)

好的伙计们,我想通了。这很奇怪,但是 我无意中改变了一些代码,并且认为这不是什么大问题,让我解释一下,所以在我的GetItem(index);代码中

我的意思是:

ListViewItem v = new ListViewItem(....,0);
v.SubItems.Add(...);
v.SubItems.Add(...);
v.SubItems.Add(...);

...... ...

好吧,我想要“优雅”我已经改变了:

ListViewItem v = new ListViewItem(....,0);
v.SubItems.AddRange( new string[] { prop1, prop2, prop3, , , ,....});

这就是问题所在,我只是把它改回来并神奇地开始工作。