1

I want to make a class that joins Table and ObservableCollection functionality. So I wrote:

public sealed class ObservableTable<T> : ObservableCollection<T>, ITable<T> where T : class
{
    private Table<T> _table;

    public Expression Expression => _table.AsQueryable().Expression;
    public Type ElementType => _table.AsQueryable().ElementType;
    public IQueryProvider Provider => _table.AsQueryable().Provider;

    public new IEnumerable<T> Items => _table;
    public new T this[int index] => _table.ElementAt(index);
    public new int Count => _table.Count();

    public ObservableTable(ref DataContext dbContext)
    {
        _table = dbContext.GetTable<T>();
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    } 

    public void InsertOnSubmit(T entity)
    {
        _table.InsertOnSubmit(entity);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
    }

    public void Attach(T entity)
    {
        _table.Attach(entity);
    }

    public void DeleteOnSubmit(T entity)
    {
        _table.DeleteOnSubmit(entity);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
    }
}

But despite _table object properly gets all the records from database, when I cast my class as ObservableCollection the collection is empty. What should I override to get it working? Aren't Items and Count properties enough?

micnyk
  • 726
  • 8
  • 27

2 Answers2

2

Because the underlying ObservableCollection<T> is empty. You're redirecting the indexer and Count properties of ObservableTable<T> to return values from your table, and you're hiding the original property implementations through new , but the actual collection, the internal storage that the ObservableCollection uses, never gets populated.

If you use the ObservableTable<T> as is, everything works. But as soon as you cast it to ObservableCollection<T>, the original implementation of the indexer and count properties will get called, and they will try to retrieve values and count from the internal storage.

Willem van Rumpt
  • 6,490
  • 2
  • 32
  • 44
  • I want to make `ObservableTable` to be `ItemsSource` of `ListView`. So it's not possible? – micnyk Sep 08 '15 at 09:20
  • 1
    Yes you can. Implement INotifyCollectionChanged and INotifyPropertyChanged, instead of inheriting from ObservableCollection. This is enough for any class to participate in the updating of (list-) controls in WPF. Google for "INotifyCollectionChanged example" and you're bound to find some implementation examples. – Willem van Rumpt Sep 08 '15 at 09:22
1

You are not overriding the properties, you are "reintroducing" them in your class and hiding the properties of the ObservableCollection<T>. Check the documentation or this question.

So if you access the Count property as ((ObservableCollection<T>)instanceOfObservableTable).Count, you actually get the hidden Count property of the base class, not your "reintroduced" property. You can access your property only like that: ((ObservableTable<T>)instanceOfObservableTable).Count.

The Count property is not virtual, so you cannot override it.

I would suggest yout to implement both the INotifyCollectionChanged and INotifyPropertyChanged interfaces in your class, so you can use it as an observable collection.

Community
  • 1
  • 1
dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • As I wrote in other comment, I want to make `ObservableTable` to be `ItemsSource` of `ListView`. Is there any possibility to do that? – micnyk Sep 08 '15 at 09:21