How to use a thread to fill a ListView in WPF and view the progress

2

I am filling ListView with a list of files, I show the file name in a TextBlock and I have a ProgressBar that should stop when the Thread ends, but I get the following exception:

  

Unhandled exception of type 'System.InvalidOperationException' in WindowsBase.dll

     

Additional information: The calling thread can not access this object because of a different thread owns it.

    public MainWindow() {
        InitializeComponent();
        //...
    }

    private void ThreadToAdd(string p) {
        path = p;
        ruta.Text = string.Format("Agregando desde {0}", p);
        porciento.Text = "";
        list.ItemsSource = fl;
        progress.Value = 0;
        progress.IsIndeterminate = true;
        Thread th = new Thread(delegate() {
            AddToList();
        });
        th.Start();
    }

    public void AddToList() {
        var files = (SearchInDirectory.GetFiles(path, "*.*", SearchInDirectory.SearchWay.AllDirectories));
        int c = 0;
        foreach (var i in files) {
            porciento.Text = string.Format("{0} elementos de {1}", ++c, files.Count());
            fl.Add(new ShellItem(i));
        }
        progress.IsIndeterminate=false;
    }

    private void window_Loaded(object sender, RoutedEventArgs e) {
        ThreadToAdd(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
    }

Then I tried Dispatcher.BeginInvoke, but the program does not respond while executing the method:

  private void ThreadToAdd(string p) {
        path = p;
        ruta.Text = string.Format("Agregando desde {0}", p);
        porciento.Text = "";
        list.ItemsSource = fl;
        progress.Value = 0;
        progress.IsIndeterminate = true;
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Callback(AddToList));
    }

    public void AddToList() {
        var files = (SearchInDirectory.GetFiles(path, "*.*", SearchInDirectory.SearchWay.AllDirectories));
        int c = 0;
        foreach (var i in files) {
            porciento.Text = string.Format("{0} elementos de {1}", ++c, files.Count());
            fl.Add(new ShellItem(i));
        }
        progress.IsIndeterminate=false;
    }

    //Loaded de Window 
    private void window_Loaded(object sender, RoutedEventArgs e) {
        ThreadToAdd(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
    }
    
asked by SiretT 30.11.2017 в 14:22
source

1 answer

1

Use the Dispatcher of the view to be able to modify elements of the view in another thread:

//...

foreach (var i in files) {
    porciento.Dispatcher.BeginInvoke(new Action(delegate() {
        porciento.Text = string.Format("{0} elementos de {1}", ++c, files.Count());
    }));

    //..
}
    
answered by 30.11.2017 в 14:32