在我的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事件方法。但我不知道如何避免这种情况,因为我在添加新项目时需要列表框滚动到底部,因此最新项目可见。
答案 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);
}