none
What happened to INotifyCollectionChanged?

    Dotaz

  • After questioning my sanity for a while, I found out that INotifyCollectionChanged (and thus ObservableCollection<T>) are not supported. One of the samples uses an ObservableVector<T> class, but it doesn't quite work for anything other than object:

     

    Additional information: Unable to compute GUID for type 'Windows.Foundation.Collections.IObservableVector`1[Foo]' because the instantiation contains types that are not supported by Windows Runtime.
    
    
    when setting it as a DataContext on a control.
    15. září 2011 17:59

Odpovědi

  • Thanks for trying out the new bits. As you've noticed INotifyCollectionChanged is not recognized by XAML - this is something we're looking into changing into the future.

    Currently there is a known bug where where only ObservableVector<object> works, this is something that will be fixed in a future release.


    Base Class Library Team (BCL) | My Blog: http://davesbox.com
    • Označen jako odpověď GrayShade 16. září 2011 7:18
    16. září 2011 6:55

Všechny reakce

  • Thanks for trying out the new bits. As you've noticed INotifyCollectionChanged is not recognized by XAML - this is something we're looking into changing into the future.

    Currently there is a known bug where where only ObservableVector<object> works, this is something that will be fixed in a future release.


    Base Class Library Team (BCL) | My Blog: http://davesbox.com
    • Označen jako odpověď GrayShade 16. září 2011 7:18
    16. září 2011 6:55
  • I have a custom class in my Metro project called SearchResult. Its properties are all basic types (string, DateTime, etc). Then I create an ObservableCollection<SearchResult> that I want to set as the Source for a CollectionViewSource.

     

    Since ObservableCollection<T> doesn't support change tracking in Metro I've included the ObservableVector.cs file from the Binding sample into my project. When it's time for me to set the ObservableCollection<SearcResult> as the Source, I call ObservableCollection<SearcResult>.ToObservableVector<SearchResult>. However, at runtime I get the following exception:


    An exception of type 'System.BadImageFormatException' occurred in imagebox.exe but was not handled in user code
     
    Additional information: Unable to compute GUID for type 'Windows.Foundation.Collections.IObservableVector`1[ImageBox.Search.SearchResult]' because the instantiation contains types that are not supported by Windows Runtime.


    If I make everything <object> instead of <SearchResult> it works. In other words, if instead of using ObservableCollection<SearcResult> I use ObservableCollection<object> and call ToObservableVector<object> everything works. But then, of course, my collection isn't typed.


    Is there any way to get change tracking and keep my typed collections?



    • Upravený jbienz 16. září 2011 7:21
    16. září 2011 7:19
  • You could write a type-safe wrapper or only implicitly implement IObservableVector<object>. Somewhat like:

    class ObservableVectorWrapper<T> : IObservableVector<T>, IObservableVector<object>
    {
        public Add(T item) // or was it Append?
        {
            (this as IObservableVector<object>).Add(item);
        }
    
        IObservableVector<object>.Add(object item) { /* ... */ }
    
        /* ...*/
    }
    
    


     


    16. září 2011 7:21
  • But isn't that what the ObservableVector<T> class does in the Binding sample?

     

    I'm referring to this sample BTW:

     

    http://code.msdn.microsoft.com/windowsapps/Data-Binding-7b1d67b5

    16. září 2011 7:24
  • The class in the sample implements IObservableVector<T>, but it can only work for object. You could implicitly implement IObservableVector<object> but have type-safe methods to add items and so on. Alternatively, you could write a generic class that uses IObservableVector<object> and casts and when it starts working you can just replace that with ObservableVector<T>.
    16. září 2011 7:28
  • As mentioned below, there's currently a bug that prevents this from working. This should work in a future release.
    Base Class Library Team (BCL) | My Blog: http://davesbox.com
    16. září 2011 15:05
  • @jbienz - just to be clear, related to:

    "If I make everything <object> instead of <SearchResult> it works. In other words, if instead of using ObservableCollection<SearcResult> I use ObservableCollection<object> and call ToObservableVector<object> everything works. But then, of course, my collection isn't typed.


    Is there any way to get change tracking and keep my typed collections?"

    For the Build bits, you need to use ObservableVector<object>.

    Joe

    16. září 2011 16:49
  • Why is IObservableVector<T> generic in the first place? The IVectorChangedEventArgs you eventually get in the notification event doesn't use the type argument. And for the scenario where ItemsControl consumes that interface (currently the only scenario in which I'd use this, I think) it can't have any expectations about what T will be. It's working with a collection of what are ultimately someone else's objects.

    ItemsControl is just as much in the dark with this being a generic interface as it would be if it were just IObservableVector with no type parameters.

    29. září 2011 7:03
  • For the Build bits, you need to use ObservableVector<object>.


    Is ObservableVector going to replace ObservableCollection?  Will ObservableCollection be updated to actually work? 
    5. října 2011 21:27
  • We're investigating how to make this integration better.
    Base Class Library Team (BCL) | My Blog: http://davesbox.com
    6. října 2011 0:42
  • As others have stated, the issue is that WinRT uses IObservableVector, whereas ObservableCollection exposes INotifyCollectionChanged. To solve the problem I have created a little adapter that you can use within a value converter as follows:

     

    <ItemsControl ItemsSource="{Binding Path=MyCollection, Converter={StaticResource ObservableCollectionAdapter}}"/>
    

     

    You can read about it here:

    http://www.scottlogic.co.uk/blog/colin/2011/10/using-observablecollection-with-winrt-via-a-little-shim/

    Regards, Colin E.

    6. října 2011 7:43
  • In case other folks run into this problem in the future, I want to warn people that the ObservableVector<T> implementation, as well as the ToObservableVector<object> extension method, in the data binding sample does not work like you would expect.

    ObservableVector<T> takes an INotifyCollectionChanged as a constructor argument as if it were a wrapper capable of forwarding collection change notifications from your ObservableCollection through the IObservableVector implementation.  It doesn't.  

     

            public ObservableVector(INotifyCollectionChanged list)
            {
                if (list is IList<T>)
                {
                    _internalCollection = list as IList<T>;
                    _readOnlyCollection = new ReadOnlyCollection<T>((IList<T>)list);
                }
                else
                {
                    throw new Exception("Must implement IList<T>");
                }
            }
    
    

     

    The INotifyCollectionChanged argument is cast to an IList and used as a backing store for the vector implementation.   If you add additional items to list (your ObservableCollection), the change notifications are not propagated.

    Also, since ObservableVector<T> is generic, you would think you could use it to hold any type (ie ObservableVector<MyClass>).  You can't.  You have to create an ObservableVector<object>.

    If all you want is something that behaves like ObservableCollection, my suggestion would be to

    • Copy the ObservableVector<T> class from the data binding sample
    • Make it not generic 
    public class ObservableVector : IObservableVector<object>, IList<object>, IEnumerable<object>, IEnumerable
    {
    
    • Make the constructor take no arguments and just create innerList in the constructor
            public ObservableVector()
            {
                _internalCollection = new List<object>(); ;
                _readOnlyCollection = new ReadOnlyCollection<object>(_internalCollection);
            }
    
    
    • Use ObservableVector anywhere you would use an ObservableCollection to hold you over till the beta is released.

    If you want to keep using ObservableCollection then you will need to wire up the collection change events your self in the ObservableVector implementation.

     

    Hope this helps.



    9. prosince 2011 3:50
  • @Robert - we believe this to be fixed and that ObservableCollection works fine now...

    Tim Heuer | Program Manager, XAML | http://timheuer.com/blog | @timheuer

    (if my post has answered your question, please consider using the 'mark as answer' feature in the forums to help others)

    9. března 2012 17:56
  • I've been reviewing various posts about adding/removing items from the collection doesn't update the gridview.  Some of the posts are from last fall. 

    @Tim - are you saying that the ObservableCollection works in that scenario?  Or are developers still required to do some sort of "clear" and/or reassign the data context everytime an item is added or removed?  Can you or someone post an example that works with the Release Preview?

    22. června 2012 2:17
  • We have Win8 RTM today. Does it mean this issue is fixed?

    16. srpna 2012 3:36
  • @JenTran - the need for the ObservableVector<object> has been removed since Consumer Preview.  ObservableCollection<T> works fine now.

    Tim Heuer | Program Manager, XAML | http://timheuer.com/blog | @timheuer

    (if my post has answered your question, please consider using the 'mark as answer' feature in the forums to help others)

    16. srpna 2012 15:46