The DataGrid won't attempt adding new rows to my CollectionView descendant

Jun 25, 2009 at 3:28 PM

I am trying to make my own virtual list class that will request a page worth of records from the server at a time.

Part of the solution is creating my own ListViewCollection descendant. It overrides the SortDescriptions property so I can perform the sort on the server side, rather than pull everything from the server and sort it on the client-side.

I've managed scrolling and sorting. Now I need the ability to add new rows.

The first attempt implemented IList.Add, but I observed that it was called before the row was fully commited. Plus I could not get it working properly (it jumped all over the place).

This is why I started looking at the IEditableCollectionView. It looks like it allows me to instantiate an instance of a new item without adding it to the list itself. Until CommitNew() of course.

But. It does not work. The empty row at the bottom of the grid is now missing.

A quick peek at the datagrid's source suggests that CollectionView.NewItemPlaceHolder is null and AFAICT this is needed. I don't see how I can override it?

Unfortunately I do not have access to the source to any of the CollectionView classes. They are unavailable from MS' symbol servers.

Jul 8, 2009 at 12:32 PM
Edited Jul 8, 2009 at 12:43 PM

My hunch about CollectionView.NewItemPlaceHolder was wrong.

ListCollectionView seem to be depending on implementing IEditableCollectionView itself.

In the following class, IsAddingNew, IsEditingItem, CanAddNew, CanRemove are called. The other stubs are not touched. The result is an empty datagrid. (In my production code I have a meaningful IEditableCollectionView implementation) Removing the IEditableCollectionView interface implementation will return the grid to standard behaviour (list one item as per my example below).

    public class RMDataTable: ListCollectionView, IEditableCollectionView
    {
        public RMDataTable(IList AList) : base(AList) { }

        #region IEditableCollectionView Members

        object IEditableCollectionView.AddNew()
        {
            throw new NotImplementedException();
        }

        bool IEditableCollectionView.CanAddNew
        {
            get { return true; }
        }

        bool IEditableCollectionView.CanCancelEdit
        {
            get { return true; }
        }

        bool IEditableCollectionView.CanRemove
        {
            get { return true; }
        }

        void IEditableCollectionView.CancelEdit()
        {
            throw new NotImplementedException();
        }

        void IEditableCollectionView.CancelNew()
        {
            throw new NotImplementedException();
        }

        void IEditableCollectionView.CommitEdit()
        {
            throw new NotImplementedException();
        }

        void IEditableCollectionView.CommitNew()
        {
            throw new NotImplementedException();
        }

        object IEditableCollectionView.CurrentAddItem
        {
            get { throw new NotImplementedException(); }
        }

        object IEditableCollectionView.CurrentEditItem
        {
            get { throw new NotImplementedException(); }
        }

        void IEditableCollectionView.EditItem(object item)
        {
            throw new NotImplementedException();
        }

        bool IEditableCollectionView.IsAddingNew
        {
            get { return false; }
        }

        bool IEditableCollectionView.IsEditingItem
        {
            get { return false; }
        }

        NewItemPlaceholderPosition IEditableCollectionView.NewItemPlaceholderPosition
        {
            get;
            set;            
        }

        void IEditableCollectionView.Remove(object item)
        {
            throw new NotImplementedException();
        }

        void IEditableCollectionView.RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

To test:

            var mylist = new List<RMDataRow>();
            dataGrid1.ItemsSource = new RMDataTable(mylist);
            mylist.Add(new RMDataRow() { fubar = "first", y = 5 });

 define RMDataRow with something like this:

    public class RMDataRow: INotifyPropertyChanged
    {
        private string Ffubar;
        private int Fy;
        public string fubar 
        {
            get { return Ffubar; }
            set
            {
                Ffubar = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("fubar"));
            }
        }
        public int y
        {
            get { return Fy; }
            set
            {
                Fy = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("y"));
            }
        }
        
        public event PropertyChangedEventHandler PropertyChanged;

    }

What I would like to know, is how I can take control over the new record transaction when inheriting from ListCollectionView? Another posting in this forum states that I have to inherit from CollectionView rather than implement the ICollectionView interface, so I feel a bit trapped now.

Jul 27, 2009 at 3:00 PM

I am obviously attacking this at the wrong end.

http://blogs.msdn.com/vinsibal/archive/2008/05/20/wpf-3-5-sp1-feature-ieditablecollectionview.aspx shows that ListCollectionView's IEditableCollectionView implementation depends on the items implementing the IEditableObject interface.

Fine, that takes good care of my editing needs.

But what goes on with ListCollectionView's AddNew() and CommitNew() implementation? Can my list implement an interface that will enable it to detect commits?