添加项目时,DrawItem事件被调用太多次

时间:2011-11-04 14:01:12

标签: c# winforms listbox

在我的WinForms应用程序中,我有一个计时器,每秒钟“滴答”。在这个计时器的tick方法中,我做了各种各样的事情,包括将项目添加到列表框(称为lbxLogText)。

我需要选择为某些项目的文本着色(颜色在添加项目之前决定)。因此,我将DrawMode属性设置为OwnerDrawVariable,lbxLogText_DrawItem方法如下所示:

private void lbxLogText_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    e.DrawFocusRectangle();
    e.Graphics.DrawString(logStringToAdd, 
        new Font(FontFamily.GenericSansSerif, 8),
        new SolidBrush(logStringToAddColor), e.Bounds);

    testCounter++;
    label29.Text = testCounter.ToString();
}

logStringToAdd:全球string

logStringToAddColor:全球Color - 红色或黑色。

testCounter:全局int,启动为0。

我有一个名为Log()的方法。这是在上面提到的计时器的tick方法中调用的。

这就是它的样子:

private void Log(string status)
{
    // |red, |black
    if (status != null)
    {
        if (status.Contains("|red"))
        {
            status = status.Replace("|red", "");
            logStringToAddColor = Color.Red;
        }
        else if (status.Contains("|black"))
        {
            status = status.Replace("|black", "");
            logStringToAddColor = Color.Black;
        }
        logStringToAdd = status;
        lbxLogText.Items.Add(new object());
    }

    // scroll to bottom
    lbxLogText.SetSelected(lbxLogText.Items.Count - 1, true);
    lbxLogText.SetSelected(lbxLogText.Items.Count - 1, false);
}

status:可能是“系统工作正常。|黑色”,或“系统无法正常工作。|红色”(例如)。此参数在Log-call之前更新(当然)。

此代码在某种程度上可以正常工作。我有以下问题:

  • 运行程序时,我可以在label29看到testCounter变量不是每秒递增一次,就像它从1开始,然后变为3,然后是6,10 ,15,21,28,36(我想你现在有了这个模式)。这意味着DrawItem事件被称为 more ,而不仅仅是每秒。

  • 让我们说status从“asd123 | black”变为“qwe456 | red”。这意味着添加到列表框的下一个项目应为红色。好吧,它确实变红了,但列表框中的所有项目变为红色。并且所有项目的文本也更改为最新。

  • 调试时,我可以看到,当调用SetSelected方法时,它会直接进入DrawItem事件方法。但我不知道如何避免这种情况,因为我在添加新项目时需要列表框滚动到底部,因此最新项目可见。

2 个答案:

答案 0 :(得分:4)

添加新项目时,

DrawItem不会被调用一次,但ListBox中已存在的每个项都会被触发 。这就是为什么在你的情况下它被称为不止一次。

这也解释了label29模式(“1,然后变为3,然后是6,10,15,21,28,36”)因为所有项目都被重新绘制你添加一个新项目的时间。

当然,由于您使用全局变量来设置项目的颜色,因此每个项目都会使用该变量的值重新绘制 - 解释为什么所有项目都变为红色。

答案 1 :(得分:1)

正如Otiel所说,每当需要重新绘制任何项目时都会调用DrawItem,并且您正在使用全局状态来存储所有项目的文本和颜色。

要使其特定于每个项目,您可以添加一个返回文本的对象/类型实例.ToString(),但您可以在DrawItem事件中查询颜色:

struct LogItem {
  public string Text;
  public Colour ItemColour
}

private void Log(string status) { 
  LogItem item = new LogItem();
  item.Text = "Wibble";
  item.ItemColour = Colours.Red;
  lbxLogText.Items.Add(item); 
}

private void lbxLogText_DrawItem(object sender, DrawItemEventArgs e) {   
  LogItem item = lbxLogText.Items[e.Index];
  e.DrawBackground();   
  e.DrawFocusRectangle();   
  e.Graphics.DrawString(item.Text,    
    new Font(FontFamily.GenericSansSerif, 8),   
    new SolidBrush(item.Color), e.Bounds);   
}