Redirecting Console.WriteLine() to Textbox

sora0419 picture sora0419 · Sep 10, 2013 · Viewed 51.8k times · Source

I'm building this application in Visual Studio 2010 using C#.

Basically there are 2 files, form1.cs (which is the windows form) and program.cs (where all the logic lies).

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

There is a Run button and a blank textbox.

When the user hits the Run button, program.cs will perform some task and constantly printing out the progress using Console.WriteLine() onto the console (command prompt).

Question: How can I print to the textbox on form1 instead of printing into command prompt? I will need to print the progress constantly without any user action.

Thanks in advance!

By the way, it doesn't have to be a textbox, it can be a label or something else that can take text. I chose textbox because it makes more sense to me.

Answer

Servy picture Servy · Sep 10, 2013

Start by creating a new TextWriter that is capable of writing to a textbox. It only needs to override the Write method that accepts a char, but that would be ungodly inefficient, so it's better to overwrite at least the method with a string.

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

In this case I've had it just accept a Control, which could be a Textbox, a Label, or whatever. If you want to change it to just a Label that would be fine.

Then just set the console output to a new instance of this writer, pointing to some textbox or label:

Console.SetOut(new ControlWriter(textbox1));

If you want the output to be written to the console as well as to the textbox we can use this class to create a writer that will write to several writers:

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

Then using this we can do:

Console.SetOut(new MultiTextWriter(new ControlWriter(textbox1), Console.Out));