2014-10-23 2 views
1

Я столкнулся с проблемой, связанной с StringBuilder и Listbox.
Я создал список в WinForm и назвал его lbOut и строку StringBuilder с именем log.StringBuilder append и Listbox

Код:

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"); 
} 
} 

Если я выполняю этот код, я должен получить:

Это испытание

Вместо этого я получаю:

Это строка testSecond

Почему это?
Я имею в виду, «Вторая строка» даже не добавляется к lbOut.


Я работаю с Visual Studio 2010, .NET 4.0 Vista.

Обновление: Спасибо всем за ответы. Сегодня я узнал немного больше. Я не могу проголосовать (пока), но я был очень доволен ответами.
Я прощал об объекте ссылки

+3

Потому что, если вы добавите «журнал» во второй раз перед его печатью, вы все равно ссылаетесь на тот же объект (который был изменен!), Когда вы печатаете его позже. Я думаю, что вы не показали нам весь ваш код, потому что, если вы выполните * этот * код, вы ничего не получите. –

ответ

2

Это происходит потому, что вы передаете в StringBuilder, а не string.

Следовательно, когда он отображается в пользовательском интерфейсе, он вызывает ToString на StringBuilder, который тем временем изменил его значение.

Возможное решение передать в string:

lbOut.Items.Add(log.ToString()); 

Или, еще лучше, создать Log метод, который записывает строку, и добавляет его в ListBox.

Что-то вроде метода ниже.Примечание Я использую 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); 
    } 
} 
0

Но вы добавляете журнал в свой lbOut. Чем вы добавляете что-то в журнал. Было бы странно, если бы он не был изменен на вашем lbOut.

0

Ваш список имеет ссылку на StringBuilder, а после того, как вы добавили его в список, вы обновили StringBuilder. Для этого используйте обычный string.

0

при добавлении журнала в lbOut вы добавляете указатель на журнал объектов, а не на значение журнала.

вы хотите напечатать/войти, что перед следующей Append или добавить значение журнала

lbOut.Items.Add(log.ToString()); 
0

Вы добавляете объект журнала в списке. И он обновляется вторым изменением текста. Если вы хотите добавить log.toString() в список, то вы должны получить то, что хотите.

0

Это потому, что вы делаете это в конструкторе. Внутри CLR видит 2 log.AppendLine вызывает оба приложения, поэтому значение log на самом деле «Это строка testSecond».

Если вы делаете точный код в Form_Load, вы получите то, что ожидаете.

1

ListBox.ObjectCollection.Add documentation дает подсказку:

Если свойство DisplayMember не уточнил член, то ListBox затем вызывает ToString метод объекта, чтобы получить текст для отображения в списке.

Звонок ToString не происходит сразу, когда вы добавляете объект. Это происходит только тогда, когда ListBox необходимо отобразить добавленный объект. Это объект, а не его string, который хранится в ListBox. Поэтому каждый раз, когда вы меняете объект, текст в ListBox изменится.

Если вы не хотите, чтобы это произошло, вы можете добавить неизменяемый объект, такой как string, к вашему ListBox.

Смежные вопросы