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
Hi,
2 things come to mind:
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.
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
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
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