简体   繁体   中英

C# Read From .txt file on change update WPF app

I am very new to C# I have a program that writes to a text file. I am trying to write some thing that can read that text file when it has changed and display the text file conext within a WPF app that I would have open.

I have the bit for the file change listener down, I know how to read the file text. I don't know how to update the text block on the WPF form with the text.

Here is the XAML

    <Window x:Class="ShowProgressBox.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" 
            Height="75" 
            Width="225" 
            ResizeMode="NoResize" 
            MouseLeftButtonDown="Window_MouseLeftButtonDown"
            WindowStyle="None"
            BorderBrush="Black"
            BorderThickness="5"
            AllowsTransparency="True"

            ToolTip="Activate window and press [ESC] key to close."
            >
        <Grid Margin="0,0,-10,0" IsManipulationEnabled="True" Focusable="True" >
            <TextBlock HorizontalAlignment="Center" FontSize="15" Margin="54,0,50,43" Width="121" FontFamily="Lucida Sans" ><Run FontWeight="Bold" Text="Macro Progress"/></TextBlock>
            <Image Source="C:\Users\Desktop\code-512.png" HorizontalAlignment="Left" Height="44" VerticalAlignment="Top" Width="54" RenderTransformOrigin="0.494,0.484"/>
            <TextBlock HorizontalAlignment="Center" Margin="46,22,20,0" TextWrapping="Wrap" Text="{Binding FileText}" VerticalAlignment="Top" Height="33" Width="159"/>
        </Grid>
    </Window>

The code behind looks like the following:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Security.Permissions;
    using System.IO;
    using System.Security.Permissions;


    namespace ShowProgressBox
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public string FileText { get; set; }

            public MainWindow()
            {
                InitializeComponent();
                this.Topmost = true;
                this.ShowInTaskbar = false;
                this.Top = 10;
                this.Left = 10;
                this.PreviewKeyDown += new KeyEventHandler(HandleEsc);
                RunWatch();
            }

            private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                this.DragMove();
            }

            private void HandleEsc(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Escape)
                {
                    Close();
                }
            }

            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public static void RunWatch()
            {
                FileSystemWatcher watcher = new FileSystemWatcher();

                // Watch for changes in LastAccess and LastWrite times, and the renaming of files or directories. 
                watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                // FILE TO WATCH PATH AND NAME. 
                watcher.Path = @"C:\Users\Desktop\";
                watcher.Filter = "test.ini";
                // Add event handlers.
                watcher.Changed += new FileSystemEventHandler(OnChanged);
                watcher.Created += new FileSystemEventHandler(OnChanged);
                watcher.Deleted += new FileSystemEventHandler(OnChanged);
                watcher.Renamed += new RenamedEventHandler(OnRenamed);
                // Begin watching.
                watcher.EnableRaisingEvents = true;
            }

            // Define the event handlers. 
            private static void OnChanged(object source, FileSystemEventArgs e)
            {
                //THE FILE CHANGED NOW LET'S UPDATE THE TEXT.

                string Text;

                try
                {
                    //Read file update the Graphical User Interface 
                   FileText = File.ReadAllText("ShowProgress.ini");

                }
                catch (System.IO.FileNotFoundException)
                {
                    FileText = "File not found.";
                }
                catch (System.IO.FileLoadException)
                {
                    FileText = "File Failed to load";
                }
                catch (System.IO.IOException)
                {
                    FileText = "File I/O Error";
                }
                catch (Exception err)
                {
                    FileText = err.Message;
                }
            }

            private static void OnRenamed(object source, RenamedEventArgs e)
            {
                // There will be code here to re-create file if it is renamed
            }
        }
    }

In brief, all you are missing is a raising a PropertyChanged event. This is how the binding target acknowledge the GUI that it's time for updating the screen.

But, a bit more than that is the bugs you are having using FileSystemWatcher (ie You are watching test.ini but you are reading file text in ShowProgress.ini and the file path is missing) and the fact that you should try to learn WPF in a MVVM way. So, try out the code that I do for you.

public class MainViewModel : ViewModelBase
{
    private readonly string pathToWatch;
    private const string FileToWatch = "test.ini";

    private string fileText;
    public string FileText
    {
        get { return fileText; }
        set
        {
            if (fileText == value) return;
            fileText = value;
            OnPropertyChanged();
        }
    }

    public MainViewModel()
    {
        pathToWatch = Environment.GetEnvironmentVariable("UserProfile") + @"\DeskTop\";

        RunWatch();
    }

    public void RunWatch()
    {
        var watcher = new FileSystemWatcher();

        // Watch for changes in LastAccess and LastWrite times, and the renaming of files or directories. 
        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
        // FILE TO WATCH PATH AND NAME. 
        watcher.Path = pathToWatch;
        watcher.Filter = FileToWatch;
        // Add event handlers.
        watcher.Changed += OnChanged;
        watcher.Created += OnChanged;
        watcher.Deleted += OnChanged;
        watcher.Renamed += OnRenamed;
        // Begin watching.
        watcher.EnableRaisingEvents = true;
    }

    // Define the event handlers. 
    private void OnChanged(object source, FileSystemEventArgs e)
    {
        //THE FILE CHANGED NOW LET'S UPDATE THE TEXT.

        try
        {
            //Read file update the Graphical User Interface 
            FileText = File.ReadAllText(pathToWatch + FileToWatch);
        }
        catch (FileNotFoundException)
        {
            FileText = "File not found.";
        }
        catch (FileLoadException)
        {
            FileText = "File Failed to load";
        }
        catch (IOException)
        {
            FileText = "File I/O Error";
        }
        catch (Exception err)
        {
            FileText = err.Message;
        }
    }

    private static void OnRenamed(object source, RenamedEventArgs e)
    {
        // There will be code here to re-create file if it is renamed
    }

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM