EditLevel Mismatch - what am I doing wrong?

EditLevel Mismatch - what am I doing wrong?

Old forum URL: forums.lhotka.net/forums/t/11608.aspx


gajit posted on Saturday, September 29, 2012

Hi gents,

Have an issue.

I have a Parent/Children BO that requires that the Children (BusinessBindListBase) is sorted by a SequenceNo column.

I tried to adopt a SortedBindingList methodology with this, but no matter how I approach it, when I attempt to Save the Parent, I get an EditLevel Mismatch.

Basically, in the UI (Windows Forms), I have up/down buttons that allow the user to move a schedule's sequence up or down.

This is what I have tried in the "up" event, all of which cause the same issue:

    Private Sub btnUp_Click(sender As System.Object, e As System.EventArgs) Handles btnUp.Click

        ' we want to move a service up in the schedule
        Dim row As Integer = ProjectSchedulesDataGridView.CurrentCell.RowIndex
        If row < 1 Then Exit Sub

        Dim pProjectSchedule As ProjectSchedule = mPROJECT.ProjectSchedules(row - 1)
        mPROJECT.ProjectSchedules(row - 1) = mPROJECT.ProjectSchedules(row)
        mPROJECT.ProjectSchedules(row) = pProjectSchedule

        ApplyAuthorizationRules()

    End Sub

or)

    Private Sub btnUp_Click(sender As System.Object, e As System.EventArgs) Handles btnUp.Click

        ' we want to move a service up in the schedule
        Dim row As Integer = ProjectSchedulesDataGridView.CurrentCell.RowIndex
        If row < 1 Then Exit Sub


        Dim seqno As Integer = ProjectSchedulesDataGridView("SequenceNo", row).Value
        Dim contractno As String = ProjectSchedulesDataGridView("SKED_ContractNo", row).Value

        Dim prevseqno As Integer = ProjectSchedulesDataGridView("SequenceNo", row - 1).Value
        Dim prevcontractno As String = ProjectSchedulesDataGridView("SKED_ContractNo", row - 1).Value

        For Each item As ProjectSchedule In mPROJECT.ProjectSchedules

            If item.ContractNo = contractno Then
                item.SequenceNo = prevseqno
            End If

            If item.ContractNo = prevcontractno Then
                item.SequenceNo = seqno
            End If

        Next

        ApplyAuthorizationRules()

    End Sub

or)

    Private Sub btnUp_Click(sender As System.Object, e As System.EventArgs) Handles btnUp.Click

        ' we want to move a service up in the schedule
        Dim row As Integer = ProjectSchedulesDataGridView.CurrentCell.RowIndex
        If row < 1 Then Exit Sub

        mPROJECT.ProjectSchedules.Swap(row, row - 1)
        ApplyAuthorizationRules()

    End Sub

In this last attempt, I created a method in my collection object that looks like this:

    Public Sub Swap(_fromposition As Integer, _toposition As Integer)

        Dim fromschedule As ProjectSchedule = Me(_fromposition) _
        , toschedule As ProjectSchedule = Me(_toposition)

        Me(_toposition) = fromschedule
        Me(_fromposition) = toschedule

        Dim id As Integer
        For id = 0 To Me.Count - 1
            Me(id).SequenceNo = id + 1
        Next id

    End Sub

None of which are working.

Any ideas?

I tested to see what happens if I just make a random change to some column data in one of the children;

mPROJECT.ProjectSchedules(0).ContractNo = "123"

and that saves with no problem.

Any ideas?

Thanks,

Graham

 

 

 

 

 

 

 

 

JonnyBee replied on Sunday, September 30, 2012

Hi,

2 things come to mind:

  1. You should NOT set the items in the list. This will add the new item and remove the original (and add it to deleted items) and actually your item (row)  will be in the list at 2 different positions and CSLA lists will notify the UI of the changes by raising OnListChanged event per action. 
  2. You should make sure that the "current item" is not in edit mode in the datagridview

So NOT like this:

        Dim pProjectSchedule As ProjectSchedule = mPROJECT.ProjectSchedules(row - 1)
        mPROJECT.ProjectSchedules(row - 1) = mPROJECT.ProjectSchedules(row)
        // here - row will be at 2 positions in list, row and row-1, and datagridview will get notification by OnListChanged
        // and pProjectSchedule item has been added to DeletedItemsList.

        // This is a potetial large problem and should NOT be done this way.
        mPROJECT.ProjectSchedules(row) = pProjectSchedule

This should work:

    Private Sub btnUp_Click(sender As System.Object, e As System.EventArgs) Handles btnUp.Click

        ' we want to move a service up in the schedule
        Dim row As Integer = ProjectSchedulesDataGridView.CurrentCell.RowIndex
        If row < 1 Then Exit Sub

        ProjectSchedulesDataGridView.EndEdit()

        Dim seqno As Integer = ProjectSchedulesDataGridView("SequenceNo", row).Value
        Dim contractno As String = ProjectSchedulesDataGridView("SKED_ContractNo", row).Value

        Dim prevseqno As Integer = ProjectSchedulesDataGridView("SequenceNo", row - 1).Value
        Dim prevcontractno As String = ProjectSchedulesDataGridView("SKED_ContractNo", row - 1).Value

        For Each item As ProjectSchedule In mPROJECT.ProjectSchedules

            If item.ContractNo = contractno Then
                item.SequenceNo = prevseqno
            End If

            If item.ContractNo = prevcontractno Then
                item.SequenceNo = seqno
            End If

        Next

        ApplyAuthorizationRules()

    End Sub

Just make sure that the "current row" in the datagrid is not in EditMode by calling <dataGridView>.EndEdit().
IE: The DataGridView will call BeginEdit/CancelEdit/EndEdit a number of times through DataBinding and assumes total ownership of the object.

gajit replied on Sunday, September 30, 2012

Thanks Jonny - I'll give it a try...  such a shame I have to address this in the UI because of Winforms limitations on binding list sorts. Oh well...

Will give it a try.

 

Thanks,

Graham

 

 

 

 

gajit replied on Sunday, September 30, 2012

OK Jonny,

It kind of works - in that what you suggested is correct - and I had foiund that before. But that solution was dependent on my datagridview being bound to a sortedbindinglist, so that I could maintain the "Sort" of SequenceNo.

So, with your fix in place.

I Call a method "RefreshSchedules" - with the intent of just pulling the current collection into a the sorted list and displaying it:

     Private Sub RefreshSchedules()

        ProjectSchedulesDataGridView.EndEdit()

        sortedScheduleList = New Csla.SortedBindingList(Of ProjectSchedule)(mPROJECT.ProjectSchedules)
        sortedScheduleList.ApplySort("SequenceNo", ListSortDirection.Ascending)

        ProjectSchedulesDataGridView.DataMember = ""
        ProjectSchedulesDataGridView.DataSource = sortedScheduleList

    End Sub

The same error occurs at save time.

Could it be something to do with the initial bindings?

ProjectScheduleDatagridView has a datasource of ProjectSchedulesBindingSource - which in turn has a Datasource=ProjectBindingSource/DataMember=ProjectSchedules

I'm sure I'm close...

Thanks again,

Graham

 

 

 

 

gajit replied on Sunday, September 30, 2012

I figured it out Jonny...

My RefreshSchedules (which I call after any remove,assign or moving around of the sequenceno's, now looks like this:

    Private Sub RefreshSchedules()

        With ProjectSchedulesBindingSource

            .EndEdit()

            sortedScheduleList = New Csla.SortedBindingList(Of ProjectSchedule)(mPROJECT.ProjectSchedules)
            sortedScheduleList.ApplySort("SequenceNo", ListSortDirection.Ascending)

            .DataMember = ""
            .DataSource = sortedScheduleList

        End With

    End Sub

Rather than setting the datasource on the gridview, I'm setting it directly to the binding source... I "think" that works...

Thanks again,

Graham.

 

 

Copyright (c) Marimer LLC