5

In wpf, I have a textbox, the content of it coming from a txt file.

in code behine it looks like:

public MyWindow()
{
    InitializeComponent();
    ReadFromTxt();
}
void Refresh(object sender, RoutedEventArgs e)
{
    ReadFromTxt();
}

void ReadFromTxt()
{
    string[] lines = System.IO.File.ReadAllLines(@"D:\Log.txt");
    foreach (string line in lines)
    {
        MyTextBox.AppendText(line + Environment.NewLine);
    }
}

The thing is that the txt file content is changing during the runtime, is it possible to be synchronized with those changes? I mean that the textbox content would be change if the txt file is changed. if It's possible please give some code example i c# or XAML.

My solution for now is that I made a "Refresh" button that reads again from the txt file

maccettura
  • 10,514
  • 3
  • 28
  • 35
Flufy
  • 309
  • 2
  • 15
  • 3
    You need FileSystemWatcher... You can take look https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.changed%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 – Adem Catamak May 18 '18 at 18:31

4 Answers4

3

You can configure FileSystemWatcher. I added FileWatcherConfigure function as an example.

Whenever file changes, FileChanged event will be published. You should trigger the RefreshTextbox method with that event.

FileSystemWatcher fileWatcher = new FileSystemWatcher();
string filePath = @"./Log.txt";
public MainWindow()
{
    InitializeComponent();

    ReadFromTxt();
    FileWatherConfigure();
}

public void FileWatherConfigure()
{
    fileWatcher.Path = System.IO.Path.GetDirectoryName(filePath);
    fileWatcher.Filter = System.IO.Path.GetFileName(filePath);
    fileWatcher.Changed += FileWatcher_Changed;
    fileWatcher.EnableRaisingEvents = true;
}

private void FileWatcher_Changed(object sender, FileSystemEventArgs e)
{
    Thread.Sleep(TimeSpan.FromSeconds(1));

    ReadFromTxt();
}


void ReadFromTxt()
{
    string[] lines = System.IO.File.ReadAllLines(filePath);
    MyTextBox.Dispatcher.Invoke(() => { this.MyTextBox.Text = string.Join(Environment.NewLine, lines); });
}
Adem Catamak
  • 1,987
  • 2
  • 17
  • 25
2

You need a FileSytemWatcher that will trigger an event that you can use to refresh the content of your textbox automatically.

I am using the following in a project I am working on to detect new and updated file.

I watch for the:

  • LastAccess: To get an event when the file has been changed
  • LastWrite: To get an event when the file has been changed
  • FileName: To get an event when a file is renamed that would match

Please note that I am clearing the textbox each time to avoid duplicated lines (your code would append the whole file to the existing content)

public class MyWindow : Window
{
  public MyWindow()
  {
    InitializeComponent();

    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = @"D:\";
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
    watcher.Filter = "Log.txt";

    // Add event handlers.
    watcher.Changed += new FileSystemEventHandler(OnFileChanged);
    watcher.Created += new FileSystemEventHandler(OnFileChanged);
    watcher.Renamed += new RenamedEventHandler(OnFileRenamed);

    // Begin watching.
    watcher.EnableRaisingEvents = true;

    ReadFromTxt();
  }

  private void OnFileChanged(object source, FileSystemEventArgs e)
  {
    ReadFromTxt();
  }

  private void OnFileRenamed(object source, RenamedEventArgs e)
  {
    ReadFromTxt();
  }

  private void ReadFromTxt()
  {
    // The easiest way is to just replace the whole text
    MyTextBox.Text = "";
    if (System.IO.File.Exists(@"D:\Log.txt") == false)
    {
      return;
    }
    string[] lines = System.IO.File.ReadAllLines(@"D:\Log.txt");
    foreach (string line in lines)
    {
      MyTextBox.AppendText(line + Environment.NewLine);
    }
  }
}
Pic Mickael
  • 1,244
  • 19
  • 36
0

Just to clarify on other answers, FileSystemWatcher can be an option but you should definately consider polling as an alternative. For readability (opinion-based) and reliability (see this thread). Note that there is many other posts that underline issues concerning the use of FileSystemWatcher.

And by polling I mean look for changes on specific periodic periods. An option would be to use a Timer and look for changes and act accordingly.

scharette
  • 9,437
  • 8
  • 33
  • 67
-1

View :

<TextBox Text="{Binding myText}"/>

Model :

private string _myText;
public string MyText{
    get { return _myText; }
    set { _myText = value;
          NotifyPropertyChanged();
}

Implement INotifyPropertyChangedto your Window And change the property MyText and not MyTextBox

omega478
  • 7
  • 4
  • That's not what he asked. He asked to be able to detect changes in the file to update the textbox with the latest content automatically. – Pic Mickael May 18 '18 at 18:52