【问题标题】:Invalidate only a single item in ListBox仅使 ListBox 中的单个项目无效
【发布时间】:2011-10-21 05:32:37
【问题描述】:

无论如何只能使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);

【问题讨论】:

    标签: c# winforms listbox listboxitem


    【解决方案1】:

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

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

    【讨论】:

    • 这不起作用。我相信这是因为基础数据没有改变和/或列表不使用 DisplayMember。
    • 另外,我已经从 ListBox 继承,因为我在 DrawItem 中进行绘图。我会用更多信息更新我的问题。
    【解决方案2】:

    好吧,我傻了。感谢@LarsTech,我决定再次查看ListBox 函数的整个列表并找到合适的函数:GetItemRectangle,它甚至是公开的!我不知道我过去一个小时是怎么错过的……

    有效的解决方案是:

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

    仍然会产生一点闪烁,但明显减少(仅当我将鼠标快速悬停在许多地方时才可见,而在移动单个项目之前会导致它)。

    【讨论】:

    • 嘿,感谢您的回答,这对我闪烁的列表框有所帮助。我也用过:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);也有助于减少闪烁。
    猜你喜欢
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多