Sortable WPF DataGrid based on ObservableCollection(of Entity)

So after getting the datagrid to sort the ADO.NET entities correctly, another issue popped up. Changes are no longer saved back to the datacontext when a row in the datagrid is changed. I tried setting the ItemsSource of the grid to an ObservableCollection(Of Entity). Sorting works, but changes are not propagated back to the underlying data source. Any ideas?
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bob LearnedCommented:
First thing I try to do with this kind of problem, is to determine the change set.  With LINQ-to-SQL, you could call GetChangeSet() with the DataContext.  

The similar construct, with the Entity Framework, is the ObjectContext.ObjectStateManager.GetObjectStateEntries.

Sample usage:

How to: Execute Business Logic When Saving Changes

Public Overloads Overrides Function SaveChanges(ByVal options As SaveOptions) As Integer

    For Each entry As ObjectStateEntry In ObjectStateManager.GetObjectStateEntries(EntityState.Added Or EntityState.Modified)
        ' Validate the objects in the Added and Modified state 
        ' if the validation fails throw an exeption. 
    Return MyBase.SaveChanges(options)
End Function

Open in new window

greenwaymgmtAuthor Commented:
This is a more complete view of my setup:

1. Lots of datagrids as follows:

<DataGrid  Name="gridTasks" ItemsSource="{Binding Path=tblTasks, Mode=TwoWay, Converter={StaticResource ListConverter}, ConverterParameter='Tasks'}"/>

2. The converter (scaled down)::
Public Function Convert()
     Select Case parameter        
          Case "Tasks"
               Return CType(value, EntityCollection(Of tblTask)).ToList
     End Select
End Function

3. Every time the data context is changed (by selecting a different project with different tasks), the applications checks for changes using:

Dim changes = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added Or EntityState.Deleted Or EntityState.Modified)

If changes.count <> 0 then db.SaveChanges() 'Where db is my ADO.NET entities object

When I don't use the converter (and hence can't sort the the grid), all the changes are caught and saved to the database. When using the converter (doesn't matter whether I convert the EntityCollection to an observable collection (see below) or a list, the ObjectStateManager does not detect any changes.

Code to convert to ObservableCollection:

Dim temp As New ObjectModel.ObservableCollection(Of tblTask)
     For Each tblTask in CType(value, EntityCollection(Of tblTask))
Return temp

I came across this blog, which I believe could solve my problem, but before changing my project completely I was wondering if there's an easier solution:

greenwaymgmtAuthor Commented:
I've done more troubleshooting and found out the following: In the Model1.Designer.vb file, everything in the Set section is executed.

    ''' <summary>
    ''' No Metadata Documentation available.
    ''' </summary>
    <EdmScalarPropertyAttribute(EntityKeyProperty:=false, IsNullable:=true)>
    Public Property Comment() As Global.System.String
            Return _Comment
        End Get
            _Comment = StructuralObject.SetValidValue(value, true)
        End Set
    End Property

But, the Dim changes = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added Or EntityState.Deleted Or EntityState.Modified), doesn't see any changes being made.

Bob LearnedCommented:
First of all, I am not a big fan of the Entity Framework--we started using NHibernate Fluent--so these problems I have probably felt during my initial investigation, but my memory has faded.  

There is a possibility:

Entity Framework Doesn't Support INotifyPropertyChanged on Some Properties

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
greenwaymgmtAuthor Commented:
Thanks that worked after some modifications. I implemented the code used in his blog, but had to manually set the Project when initializing a new row in the grid. When the grid was bound to an unsortable entitycollection, this reference was set automatically on new item initialization. Yeah, I'm starting to realize that the Entity Framework isn't too great.

Public Sub PublicInitializingNewItem(ByVal sender As System.Object, ByVal e As System.Windows.Controls.InitializingNewItemEventArgs)

        Dim newEntry As Object
        Select Case CType(sender, DataGrid).Name
            Case "gridTasks"
                newEntry = CType(e.NewItem, tblTask)
                newEntry.tblProject = db.tblProjects.Single(Function(f) f.ID = globalID)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.