只使ListBox中的单个项目无效

4
有没有办法只使 ListBox 中的单个项目失效?似乎没有获取项目矩形或特定项目是否可见的方法(除了在控件中每个像素/至少一个列中的每个像素调用 IndexFromPoint )。
这是针对 C# WinForms(不是 WPF)的。
关于我尝试做什么的更多信息:
我有一个带有许多项目的 ListBox,我希望一组“按钮”出现在您悬停在其上的项目上(例如删除的红色 X)。我已经做得很好,但是对于具有10个或更多项目的列表,每次您悬停在新项目上时,它都会导致可见重绘,因为我使整个控件失效。数据未更改,仅更改显示。
编辑:更多信息和之前的尝试
我已经子类化 ListBox 并在 OnDrawItem 中执行我的绘图,因此可以使用 ListBox 的受保护方法。
我已尝试以下内容,成功的程度不同。变量 this 是扩展的 ListBoxindex 是要绘制的项,old_index 是先前正在绘制的项。
// Causes flicker of entire list, but works
this.Invalidate();

// Causes flicker of selected item, but works
int sel_index = this.SelectedIndex;
this.SelectedIndex = old_index;
this.SelectedIndex = index;
this.SelectedIndex = sel_index;

// Does not work
if (old_index >= 0)
  this.RefreshItem(old_index);
if (index >= 0)
  this.RefreshItem(index);
2个回答

7

好的,我有些愚蠢。感谢@LarsTech的帮助,我决定再次查看整个ListBox函数列表,并找到了适当的函数:GetItemRectangle,而且它是公共的!我不知道我在过去的一个小时里怎么错过了这个...

可行的解决方案是:

if (old_index >= 0)
  this.Invalidate(this.GetItemRectangle(old_index));
if (index >= 0)
  this.Invalidate(this.GetItemRectangle(index));

现在仍然会出现一些闪烁,但明显减少了(只有在我快速鼠标悬停多个项目时才能看到,之前移动单个项目就会出现)。


1
嘿,谢谢你的回答,这对解决我的闪烁列表框问题很有帮助。我还使用了:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 来帮助减少闪烁。 - ChandlerPelhams

1

是的,但您必须通过继承它并公开 Microsoft 正在隐藏的 RefreshItem 方法来创建自己的列表框版本:

public class ListBoxEx : ListBox
{
  public new void RefreshItem(int index)
  {
    base.RefreshItem(index);
  }
}

这不起作用。我认为是因为底层数据没有改变和/或列表没有使用DisplayMember。 - coderforlife
另外,我已经从ListBox继承,因为我在DrawItem中进行绘制。我将在我的问题中更新一些更多的信息。 - coderforlife

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接