-1

I have a long list of words.I check how many times the word occurs then I add it to an ObservableCollection.Since it is a long list and the iteration takes quite a bit of time, I would like to be able to display the word after each iteration and continue to the next. Currently the words will be displayed all together after the iteration of the whole collection is done.

When debugging I noticed that the listbox(wordBox) was updated when I added a value to oWords but the value was not displayed.

Exercise4_btn.Click += async (object sender, RoutedEventArgs e) =>
        {
            oWords = new ObservableCollection<Word>();
            List<string> words = await GetWordsFromFile();

            wordBox.DataContext = oWords;
            wordBox.SetBinding(ListBox.ItemsSourceProperty, new Binding()); 

            foreach (var word in words)
            {
                await Task.Run(() =>
                {
                    int count = words.Where(w => w.Equals(word)).Count();

                    try
                    {
                        oWords.Add(new Word {Value = word, Count = count});
                    }
                    catch { }
                });
            }
        };

This is how the listbox looks in xaml

<ListBox Name="wordBox" HorizontalAlignment="Left" Height="612" Margin="460,53,0,0" VerticalAlignment="Top" Width="278"/>

And this is the class used by the ObservableCollection

public class Word
{
    public string Value { get; set; }
    public int Count { get; set; }

    public override string ToString()
    {
        return ($"{Value}\t{Count}");
    }
}
Andrea
  • 247
  • 2
  • 4
  • 14
  • Please do not post screenshots of your code and/or error messages (something to read: [Why not upload images of code on SO when asking a question?](https://meta.stackoverflow.com/a/285557/2819245), [An image of your code is not helpful](http://idownvotedbecau.se/imageofcode) and [Pictures of exceptions are not helpful](http://idownvotedbecau.se/imageofanexception/)). –  Nov 25 '18 at 19:27
  • 1
    Thank you @elgonzo I have edited my question. – Andrea Nov 25 '18 at 19:53
  • Um... why do you have a `try`-`catch` clause with an empty catch block? Why...? There are less painful ways to die... ;-) –  Nov 25 '18 at 19:58
  • 1
    Just to make my point a little clearer: A try-catch with an empty catch block is akin to what Frank Drebin does here: https://www.youtube.com/watch?v=pdFl__NlOpA ;-) –  Nov 25 '18 at 20:09
  • "_I noticed that the listbox(wordBox) was updated_" How exactly did you notice? What did you see, if you didn't see the value? Also, why do you set the `ListBox.DataContext` just to bind `ListBox.ItemsSource` against it. I wonder why you would do that instead of simply setting `ListBox.ItemsSource` to the collection. –  Nov 25 '18 at 20:14
  • Use `PropertyChangeNotification` – Zam Nov 25 '18 at 20:48
  • @elgonzo Awesome – Cleptus Nov 25 '18 at 21:16
  • You didn't deal with any error; your empty try-catch block just sweeps any exception happening there under the rug, pretending that everything is a-okay. That is not dealing with errors, that is ignoring them. As a start, remove this terrible empty try-catch block from your code. If you run your program then, what do you observe? –  Nov 25 '18 at 23:29
  • If you get an exception, note its type and the concrete exception message (and stack trace, too). It will tell you what is going wrong in your program at that moment, which in turn should hopefully inform you about how to remedy the problem. (Instead of removing the empty try-catch block, you might alternatively expand it with some meaningful exception handling, that -- for example -- could show the exception information i mentioned in a message box) –  Nov 25 '18 at 23:42
  • Empty `try catch` blocks are wrong, but I think you may have got this from the previous comments. You are using the TPL to offload the work from the main thread of execution and updating the `ObservableCollection` on this which I suspect is where things aren't then updating the User Interface, see this link to explain it: [Update UI With WPF Dispatcher And TPL](https://www.c-sharpcorner.com/article/update-ui-with-wpf-dispatcher-and-tpl/) – Coops Nov 26 '18 at 08:42
  • @Coops Thank you that worked – Andrea Nov 26 '18 at 22:58
  • @FirasAl-Husari Nice one, I'm pleased it did. It's one of the gotcha's with WPF that just needs bearing in mind. Don't forget to up-vote if you found my help useful ;-) – Coops Nov 27 '18 at 08:10
  • @Coops I don't think I have enough reputation to up-vote or I simply don't see the option to up-vote a comment , so I have give you credit in the answer. – Andrea Nov 27 '18 at 09:41
  • @FirasAl-Husari, no worries dude. I was glad to help you out :-) – Coops Nov 27 '18 at 09:57
  • Well, this so far only addresses one of the two problems present in your code. Yes, there are two. The system will tell you when those problems occur through exceptions. The one that always strikes has now been addressed (using BindingOperations.EnableCollectionSynchronization), but there is another, more insidious issue present. It is insidious because it might not always strike, its occurence depending on circumstance. I made a rather simplified example on dotnetfiddle: https://dotnetfiddle.net/cGNiaL to demonstrate this issue. (1/2) –  Nov 27 '18 at 20:44
  • (2/2) If you look at the dotnetfiddle code, you'll see that it starts 100 tasks which each add 1000 number to an ObservableCollection. However, if you run it, some exception will occur (if it doesn't happen at the first try, run the program again. It shouldn't take more than 2 or 3 attempts). Look at that exception. The exception might confuse you. Try to figure out what is going on there... (since your button is called "Exercise4", i guess it is an exercise about async/parellel programming. My last two comments here should be part of the topic the exercise is about, if my guess is correct.) –  Nov 27 '18 at 20:46

1 Answers1

0

The link in the comment provided by Coops worked for me Update UI With WPF Dispatcher And TPL

I also found another similar solution Asynchronously adding to ObservableCollection

Andrea
  • 247
  • 2
  • 4
  • 14