0

The context is that I want to expose to a ListView in the View a ListCollectionView from the ViewModel; that ViewModel updates slowly an ObservableCollection (it takes few seconds to fill the collection).

Hence, I want to update a ListCollectionView after an ObservableCollection was updated this way:

MyObservableCollection.CollectionChanged += CollectionChanged;

private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    MyListCollectionView.AddNewItem(e.NewItems);
    MyListCollectionView.CommitNew();
}

I tried to update a ListCollectionView, but it fails even with a List<>. How can I do this ?

[TestClass]
public class ListViewTests
{
    private ListCollectionView _sut;

    [TestInitialize]
    public void Setup()
    {
        var toadd = new List<int> {};
        _sut = new ListCollectionView(toadd);
    }

    [TestMethod]
    public void AddItem()
    {
        var toadd = new List<int> { 1,2,3 };
        _sut.AddNewItem(toadd);
        _sut.CommitNew();
    }
}

System.InvalidOperationException: 'AddNewItem' is not allowed for this view.

For more details, how I update the ObservableCollection:

Parallel.ForEach(ShTiffFiles, file =>
{
    var sht = new ShutterTiff(file, _aesService); // slow (small Model)
    var shtv = new ShutterTiffVignette(sht, _fastCache); // slow (small ViewModel)
    lock (_o) // make it thread safe
    {
        Application.Current.Dispatcher.Invoke(() =>
        {
            ShutterTiffObservableCollection.Add(shtv);
        });
    }
});

in the ViewModel:

private object _o = new object();
Soleil
  • 6,404
  • 5
  • 41
  • 61
  • addition to mm8 answer: `var toadd = new List { 1,2,3 }; _sut.AddNewItem(toadd);` will not work if you change `int[]` to `List` – Selvin Oct 20 '20 at 13:06
  • 1
    after update: and why ... why you whana use `ListCollectionView` ? instead `ObservableCollection` directly? ... and why if you really need to use LCV you are not using `MyListCollectionView = new ListCollectionView(MyObservableCollection)` ? then you dont need setup CollectionChanged event handler – Selvin Oct 20 '20 at 13:09
  • You can obviously only add `int` values to a `List`. Not another `List`. `toadd` should be an `int` in `AddItem()`. – mm8 Oct 20 '20 at 13:15
  • You would hardly ever create a ListCollectionView explicitly. Instead, use a CollectionViewSource: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-get-the-default-view-of-a-data-collection?view=netframeworkdesktop-4.8 – Clemens Oct 20 '20 at 13:18
  • 1
    @Selvin That's the correct point. I don't need to worry about `ListCollectionView`, I only need to add to the `ObservableCollection`. Then what is the `AddNewItem` for ? – Soleil Oct 20 '20 at 13:25
  • @Soleil-MathieuPrévot mm8 beat me and add this info to his answer, too, right before I post the comment – Selvin Oct 20 '20 at 13:27
  • Your original question included a unit test against a `ListCollectionView` so whether you "need" or not depends entirely on the context. But in general, no, you could just add items to the source collection directly. – mm8 Oct 20 '20 at 13:38
  • 1
    @mm8 Are you implying that there are several ways to update ListCollectionView ? – Soleil Oct 20 '20 at 13:41
  • @Soleil-MathieuPrévot: No. I am saying that I don't see why you need one in the first place as you can modify the source collection directly. – mm8 Oct 20 '20 at 13:44
  • @mm8 This should be stated in your answer, so I can accept it, it's the core point. Then what is the AddNewItem for ? – Soleil Oct 20 '20 at 14:03
  • I added a link to the docs where you can read about how collection views work. – mm8 Oct 20 '20 at 14:14
  • 1
    @mm8 I missed that remark indeed. Still, in that case, what is AddNewItem(Object) for ? – Soleil Oct 20 '20 at 14:23
  • For adding a new item to the view. It doesn't mean that you should use it :) – mm8 Oct 20 '20 at 14:24
  • @Soleil-MathieuPrévot: Please ask a new question if you have another issue. Don't change the original question. – mm8 Oct 21 '20 at 12:11
  • @mm8 I did not change the question, I added context details – Soleil Oct 21 '20 at 14:09

1 Answers1

2

Change the type of toadd in the Setup() method to a List<T> or any other collection that implements IList and actually provides an implementation for the Add method:

Why System.Array class implements IList but does not provide Add()

You cannot 'Add' something to an array.

It's also unclear what your test is supposed to do? Verify the functionality of the built-in ListCollectionView type? You should focus on testing your code instead of testing framework types.

*In the end, I want to update a ListCollectionView after an ObservableCollection was updated

Then wrap the ObservableCollection:

_sut = new ListCollectionView(observableCollection);

Or simply modify the ObservableCollection directly. You don't seem to need to use a ListCollectionView here. A collection view is something that the frameworks creates for you when you bind to a source collection. Please refer to the docs for more information.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • I really liked your answer. Learned a lot from it Also maybe she just wanna do some playtesting for something new "things" in the framework and don't do some actual tests – styx Oct 20 '20 at 12:59
  • @styx: Maybe. That's why I wrote "unclear". – mm8 Oct 20 '20 at 13:00
  • @Soleil-MathieuPrévot: The `ListCollectionView` wraps an array in the `Setup()` method. I edited my answer to clarify this since you also have a `toadd` in the test method. – mm8 Oct 20 '20 at 13:05