Listbox 上的 C# FileWatch 写入事件

C# FileWatch write event on Listbox

我有一个监视文件夹的 WPF 程序,我想在列表框中写下发生的每个事件。

我的问题是我有一个 class FileWatcher,但我无法将事件(创建、更改和删除)传递到列表框。

有人可以帮忙吗?

谢谢

主窗口

    public MainWindow()
    {
        InitializeComponent();

        string Location = string.Empty; //variavel que vai definir a localização da monitorização
    }

    private void btMon_Click(object sender, RoutedEventArgs e)
    {
        FolderBrowserDialog browseFolder = new FolderBrowserDialog();

        browseFolder.Description = "Selecione a pasta que deseja monitorizar. Todas as subpastas serão monitorizadas.";

        if (browseFolder.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            Location = browseFolder.SelectedPath;
            System.Windows.MessageBox.Show(Location);
        }
    } // Definição da localização que passa para o Filewatcher

    private void btInMon_Click(object sender, RoutedEventArgs e)
    {
        monitoriza = new FileWatcher(Location);
    } // Inicio da monitorização com a class FileWatcher

Class 文件观察器

public class FileWatcher
{
    public MainWindow main;

    private FileSystemWatcher _fileWatcher;

    public FileWatcher(string Location)
    {
        _fileWatcher = new FileSystemWatcher(PathLocation(Location));
        _fileWatcher.IncludeSubdirectories = true;

        _fileWatcher.Created += new FileSystemEventHandler(_fileWatcher_Created);


        _fileWatcher.EnableRaisingEvents = true;
    }

    private string PathLocation(string Location)
    {
        string value = String.Empty;

        try
        {
            value = Location;

            if (value != string.Empty)
            {
                return value;
            }
        }
        catch (Exception ex)
        {
            //Implement logging on future version

        }

        return value;

    }

    void _fileWatcher_Created(object sender, FileSystemEventArgs e)
    {
        Logging.Log(String.Format("Evento criado por " + Environment.UserName + " Em " + DateTime.Now + " File Created: Patch:{0}, Name:{1}", e.FullPath, e.Name));  
    }
}

由于您正在实施 WPF 应用程序,因此请利用其数据绑定功能。也就是说,您不需要在 FileWatcher class.

中引用 MainWindow class

您需要的是 FileWatcher class 中所有触发事件的字符串集合,它绑定到您的 ListBox。

在您的 MainWindow.xaml 中,添加以下行:

    <ListBox Grid.Row="3" ItemsSource="{Binding FileWatcher.EventsFired}"/>

将您的 MainWindow.xaml.cs 更改为以下内容:

public partial class MainWindow : Window, INotifyPropertyChanged //Notify the UI when changes occur
{
    private string _location;
    private FileWatcher _fileWachter;

    public FileWatcher FileWatcher
    {
        get
        {
            return _fileWachter;
        }
        set
        {
            // this makes your FileWatcher observable by the ui
            _fileWachter = value;
            OnPropertyChanged();
        }
    }

    public string Location
    {
        get
        {
            return _location;
        }
        set
        {
            _location = value;
            OnPropertyChanged();
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        Location = string.Empty; //variavel que vai definir a localização da monitorização
        // DO NOT FORGET ABOUT THIS ONE
        // REGISTER FOR NotifyPropertyChanged
        DataContext = this;

    }

    private void btMon_Click(object sender, RoutedEventArgs e)
    {
        FolderBrowserDialog browseFolder = new FolderBrowserDialog();

        browseFolder.Description = "Selecione a pasta que deseja monitorizar. Todas as subpastas serão monitorizadas.";

        if (browseFolder.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            Location = browseFolder.SelectedPath;
            System.Windows.MessageBox.Show(Location);
        }
    } // Definição da localização que passa para o Filewatcher

    private void btInMon_Click(object sender, RoutedEventArgs e)
    {
        FileWatcher = new FileWatcher(Location);
    } 

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // it is good practice to check the handler for null before calling it
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

最后修改你的 FileWatcher class:

public class FileWatcher : DispatcherObject, INotifyPropertyChanged //Dispatcher object is necessary to call the right dispatcher from the background thread
{
    //collect all events from the filewatcher
    public ObservableCollection<string> EventsFired
    {
        get
        {
            return _eventsFired;
        }
        set
        {
            _eventsFired = value;
            OnPropertyChanged();
        }
    }

    private FileSystemWatcher _fileWatcher;
    private ObservableCollection<string> _eventsFired;

    public FileWatcher(string Location)
    {
        //save all fired events
        _eventsFired = new ObservableCollection<string>();

        _fileWatcher = new FileSystemWatcher(PathLocation(Location));
        _fileWatcher.IncludeSubdirectories = true;

        _fileWatcher.Created += _fileWatcher_Created;

        _fileWatcher.EnableRaisingEvents = true;
    }

    private string PathLocation(string Location)
    {
        string value = String.Empty;

        try
        {
            value = Location;

            if (value != string.Empty)
            {
                return value;
            }
        }
        catch (Exception ex)
        {
            //Implement logging on future version

        }

        return value;

    }

    void _fileWatcher_Created(object sender, FileSystemEventArgs e)
    {
        //necessary to refresh collection from background thread
        Dispatcher.BeginInvoke(DispatcherPriority.Send, new Action(() =>
        {
            EventsFired.Add(String.Format("Evento criado por " + Environment.UserName + " Em " + DateTime.Now + " File Created: Patch:{0}, Name:{1}", e.FullPath, e.Name));
        }));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
    }
}

在 MainWindow.xaml 中,您告诉 ListBox 显示文件观察器触发的所有事件(现在只有您创建的文件)。这些保存在 ObservableCollection - 一个集合中,当对集合进行更改时通知 UI,例如添加或删除项目。

必须在 OnCreated 事件上调用 Dispatcher,因为该事件是从非 ui 线程触发的。您无法修改从后台线程绑定 ui 的集合。通过使用 Dispatcher.Invoke,您将新添加的字符串发送到主线程以刷新集合。

希望对您有所帮助!