Search code examples
silverlight-4.0entity-framework-4wcf-ria-services

How to add a new entity to a domain context and immediately see it in data bound controls before SubmitChanges?


I've got a Silverlight 4 RIA Services (SP1) app using Entity Frameworks 4 CTP5. I can databind a grid or listbox to the IEnumerable loaded by the domain context and it shows data from the server. Great.

Now I want to create a new instance of MyEntity and add it to the client-side data so that the user can see the newly added entity. MyEntity is a true entity descendant, not a POCO.

The only Add method I can find is domainContext.EntityContainer.GetEntitySet<MyEntity>().Add(newobj)

This does add the new entity to the domain context, and the domainContext.HasChanges does become true, but the new entity doesn't show up in the databound controls.

How do I get the new entity to show up in the databound controls prior to SubmitChanges?

(Probably related to this SO question from years ago that never got an answer)

Here's the server side declarations of the domain service, per requests:

[EnableClientAccess()]
public class MyDomainService : LinqToEntitiesDomainService<MyObjectContext>
{
    protected override MyObjectContext CreateObjectContext()
    {
        return new MyObjectContext();
    }

    public IQueryable<MyEntity> GetMyEntities()
    {
        return this.ObjectContext.MyEntities;
    }

    public void InsertMyEntity(MyEntity MyEntity)
    {
        // ...
    }

    public void UpdateMyEntity(MyEntity currentMyEntity)
    {
        // ...
    }

    public void DeleteMyEntity(MyEntity MyEntity)
    {
        // ...
    }
}

Solution

  • I've figured this out with a combination of my own trial and error and hints provided by some of the other responses to this question.

    The key point I was missing was that it's not enough for the ViewModel to keep track of the DomainContext and hand out query results to the View for databinding. The ViewModel also has to capture and retain the query results if you want entity adds and deletes performed by the ViewModel to appear in the UI before DomainContext.SubmitChanges(). The ViewModel has to apply those adds to the collection view of the query results.

    The ViewModel collection property for View databinding. In this case I'm using the Telerik QueryableDomainServiceCollectionView, but other collection views can be used:

        public IEnumerable<MyEntity> MyEntities
        {
            get
            {
                if (this.view == null)
                {
                    DomainContextNeeded();
                }
                return this.view;
            }
        }
    
        private void DomainContextNeeded()
        {
            this.context = new MyDomainContext();
            var q = context.GetMyEntitiesQuery();
            this.view = new Telerik.Windows.Data.QueryableDomainServiceCollectionView<MyEntity>(context, q);
            this.view.Load();
        }
    

    The ViewModel function that adds a new entity for the UI to display:

    public void AddNewMyEntity(object selectedNode)
    {
        var ent = new MyEntity() { DisplayName = "New Entity" };
    
        if (selectedNode == null)
        {
            this.view.AddNew(ent);
        }
        else if (selectedNode is MyEntity)
        {
            ((MyEntity)selectedNode).Children.Add(ent);
        }
    }
    

    Other responses mentioned ObservableCollection. The query results and the collection view may not return instances of ObservableCollection. They could be just IEnumerables. What is critical is that they implement INotifyCollectionChanged and IEditableCollectionView.

    Thanks to those who contributed responses. I've +1'd each response that was helpful, but since none directly solved my problem I couldn't justify marking any as the definitive answer.