Перенаправление Console.WriteLine() в текстовое поле
Я строю это приложение в Visual Studio 2010 с использованием C#.
В основном есть 2 файла, form1.cs (который является формой окна) и program.cs (где лежит вся логика).
//form1.cs
public partial class Form1 : Form
{
//runButton_click function
}
//program.cs
class Program
{
static void Main()
{
while(blah-condition)
{
//some calculation
Console.WriteLine("Progress " + percent + "% completed.");
}
}
}
Есть кнопка Run и пустое текстовое поле.
Когда пользователь нажимает кнопку " Выполнить", program.cs выполнит некоторую задачу и будет постоянно выводить на печать прогресс, используя Console.WriteLine()
на консоль (командная строка).
Вопрос: Как я могу печатать в текстовое поле в форме 1 вместо печати в командной строке? Мне нужно будет постоянно печатать прогресс без каких-либо действий пользователя.
Заранее спасибо!
Кстати, это не обязательно текстовое поле, это может быть метка или что-то еще, что может принимать текст. Я выбрал текстовое поле, потому что оно имеет больше смысла для меня.
4 ответа
Начните с создания нового TextWriter
который способен писать в текстовое поле. Нужно только переопределить Write
метод, который принимает char
, но это было бы ужасно неэффективно, поэтому лучше переписать хотя бы метод строкой.
public class ControlWriter : TextWriter
{
private Control textbox;
public ControlWriter(Control textbox)
{
this.textbox = textbox;
}
public override void Write(char value)
{
textbox.Text += value;
}
public override void Write(string value)
{
textbox.Text += value;
}
public override Encoding Encoding
{
get { return Encoding.ASCII; }
}
}
В этом случае у меня было просто принять Control
, который может быть Textbox
, Label
или что угодно. Если вы хотите изменить его на просто Label
это было бы хорошо.
Затем просто установите вывод консоли на новый экземпляр этого модуля записи, указывая на какое-либо текстовое поле или метку:
Console.SetOut(new ControlWriter(textbox1));
Если вы хотите, чтобы вывод был записан как в консоль, так и в текстовое поле, мы можем использовать этот класс для создания модуля записи, который будет писать нескольким модулям записи:
public class MultiTextWriter : TextWriter
{
private IEnumerable<TextWriter> writers;
public MultiTextWriter(IEnumerable<TextWriter> writers)
{
this.writers = writers.ToList();
}
public MultiTextWriter(params TextWriter[] writers)
{
this.writers = writers;
}
public override void Write(char value)
{
foreach (var writer in writers)
writer.Write(value);
}
public override void Write(string value)
{
foreach (var writer in writers)
writer.Write(value);
}
public override void Flush()
{
foreach (var writer in writers)
writer.Flush();
}
public override void Close()
{
foreach (var writer in writers)
writer.Close();
}
public override Encoding Encoding
{
get { return Encoding.ASCII; }
}
}
Тогда с помощью этого мы можем сделать:
Console.SetOut(new MultiTextWriter(new ControlWriter(textbox1), Console.Out));
Не знаю, сработает ли это, но вы можете попытаться перенаправить вывод консоли.
использование Console.SetOut()
и создать производную от TextWriter
который переопределяет WriteLine()
метод и просто назначьте параметр метода вашему TextBox.Text
Должно сработать.
Я использую что-то вроде этого для списка:
public class ListBoxWriter : TextWriter //this class redirects console.writeline to debug listbox
{
private readonly ListBox _list;
private StringBuilder _content = new StringBuilder();
public ListBoxWriter(ListBox list)
{
_list = list;
}
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
public override void Write(char value)
{
base.Write(value);
_content.Append(value);
if (value != '\n') return;
if (_list.InvokeRequired)
{
try
{
_list.Invoke(new MethodInvoker(() => _list.Items.Add(_content.ToString())));
_list.Invoke(new MethodInvoker(() => _list.SelectedIndex = _list.Items.Count - 1));
_list.Invoke(new MethodInvoker(() => _list.SelectedIndex = -1));
}
catch (ObjectDisposedException ex)
{
Console.WriteLine(Resources.Exception_raised + " (" + ex.Message + "): " + ex);
}
}
else
{
_list.Items.Add(_content.ToString());
_list.SelectedIndex = _list.Items.Count - 1;
_list.SelectedIndex = -1;
}
_content = new StringBuilder();
}
}
и в моем основном приложении:
_writer = new ListBoxWriter(DebugWin); // DebugWin is the name og my listbox
Console.SetOut (_writer);
Положил textbox
на бланке (multiple lines
включен) или текстовая область, то вы можете сделать в вашем цикле
txtOutput.Text += "Progress " + percent + "% completed." + Environment.NewLine();