StringBuilder append and Listbox
本文关键字:Listbox and append StringBuilder | 更新日期: 2023-09-27 18:27:30
我在StringBuilder和Listbox上遇到了一个明显的问题。
我在WinForm上创建了一个Listbox,并称之为lbOut和一个名为log的StringBuilder字符串。
代码:
public partial class formMain : Form
{
StringBuilder log = new StringBuilder();
public formMain()
{
InitializeComponent();
log.AppendLine("This is a test");
lbOut.Items.Add(log);
log.AppendLine("Second line");
}
}
如果我执行此代码,我应该得到:
这是个测试
相反,我得到:
这是测试第二行
为什么?
我的意思是,"第二行"甚至没有添加到lbOut中。
我在Vista上使用Visual Studio 2010,.Net 4.0。
更新:感谢大家的回答。我今天学到了更多。我(还不能投票(,但我对给出的答案非常满意。
我已经忘记了对象引用
发生这种情况是因为您传入了StringBuilder
,而不是string
。
因此,当它显示在UI中时,它会在StringBuilder
上调用ToString
,同时更改了它的值。
一个可能的解决方案是传入string
:
lbOut.Items.Add(log.ToString());
或者,更好的是,创建一个记录字符串并将其添加到ListBox
的Log
方法。
类似于下面的方法。注意 如果需要,我会使用 Invoke
,因此 Log
方法是线程安全的:
private void Log(string text)
{
log.AppendLine(text);
if (lbOut.InvokeRequired)
{
lbOut.Invoke((MethodInvoker)delegate()
{
lbOut.Items.Add(text);
});
}
else
{
lbOut.Items.Add(text);
}
}
ListBox.ObjectCollection.Add
文档提供了一个提示:
如果
DisplayMember
属性未指定成员,则ListBox
调用对象的ToString
方法以获取要在列表中显示的文本。
添加对象时,ToString
调用不会立即发生。仅当ListBox
需要呈现已添加的对象时,才会发生这种情况。ListBox
保留的是对象,而不是其string
表示。因此,每次更改对象时,ListBox
中的文本都会更改。
如果您不希望发生这种情况,则可以将不可变对象(例如string
(添加到ListBox
中。
,您将日志添加到lbOut中。比你添加一些东西来记录。如果它没有在你的 lbOut 上改变,那就太奇怪了。
您的列表框具有对StringBuilder
的引用,在将其添加到列表框后,您更新了StringBuilder
。只需为此使用常规string
即可。
当您将日志添加到lbOut时,您是在添加指向对象日志的指针,而不是log的值。
您可能希望在下一次追加之前打印/记录它或添加 log 的值
lbOut.Items.Add(log.ToString());
将日志对象添加到列表中。它通过第二次文本更改进行更新。如果您想将log.toString()
添加到列表中,那么您应该得到您想要的。
这是因为您在构造函数中执行此操作。CLR 在内部看到 2 日志。AppendLine 调用两者 a apply,因此 log 的值实际上是"这是一个测试第二行"。
如果你在Form_Load中执行完全相同的代码,你会得到你所期望的。