jjw
jjw

Reputation: 294

How to bind the Text of a TextBox with a File's content?

I created the editor inheriting the TextBox.

The editor loads the data from the file like below.

public Editor()
{
    this.Text = File.ReadAllText(fileName);
}

The above code works well but the changes of the editor do not apply because not be bound with the file.

In other words, although I change the content of the editor then the changes do not apply to the file.

To do this, I need to write additional code as below.

File.WriteAllText(fileName, content);

The problem is I don't know where to put the above code.

If I put the above code onto the TextChanged event handler then the performance of the editor is lower.

But I don't know the suitable position to put the above code except for TextChanged event handler.

Is there a formulaic way to solve this problem?

Upvotes: 1

Views: 617

Answers (3)

mrbm
mrbm

Reputation: 1171

A similar way to @Sviatoslav Vovdenko's solution is this

private void Form1_Load(object sender, EventArgs e)
{
    textBox1.Text = File.ReadAllText("test.txt");

    timer1.Interval = 2000;
    timer1.Enabled = false;  //***********
}

private async void timer1_Tick(object sender, EventArgs e)
{ 
    timer1.Stop();   //***********
    await Task.Run(() => Save()); 
}

private void Save()
{
    lock (this.timer1)     //***********
        File.WriteAllText("test.txt", textBox1.Text); 
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    timer1.Stop();     //*********** skip pending save and start again
    timer1.Start();    //***********
}

Upvotes: 1

Sviatoslav Vovdenko
Sviatoslav Vovdenko

Reputation: 66

First of all, use timer to save text with some period (approx 5 sec). Save text async to avoid performance issue.

    private bool needSave;

    private object locker = new object();

    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.Text = File.ReadAllText("test.txt");

        timer1.Interval = 5000;

        timer1.Enabled = true;
    }

    private async void timer1_Tick(object sender, EventArgs e)
    {
        if (needSave)
        {
            needSave = false;

            await Task.Run(() => Save());
        }
    }

    private void Save()
    {
        lock (locker)
        {
            File.WriteAllText("test.txt", textBox1.Text);
        }
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        needSave = true;
    }

Upvotes: 2

mm8
mm8

Reputation: 169160

Is there a formulaic way to solve this problem?

No, there isn't. You as the control developer needs to decide when to write the data back to the file.

The common solution to this kind of issues is to implemement some sort of throttling behavior, i.e. when you detect a key stroke you wait x seconds before you write the data back to the storage.

Please have a look at how ReactiveUI solves this using Rx and LINQ operators. You might also use a timer that you for example start when a TextChanged event is raised.

The other option is of course to provide a button or some other input control that lets the user decide when to save.

Upvotes: 3

Related Questions