I've attached the modified project source code.
Main changes are as follows:
- using reactive observables streams through DynamicData nugget
- sfdatagrid is still bound to EmployeeDetails, a dynamically generated ReadOnlyObservableCollection
//dynamicdata binding
_SubscriptionToModelChanges = _readonlyEmployeeDetailsCacheChangeSet
.Sort(SortExpressionComparer.Ascending(i => i.EmployeeId)) //some operation
.ObserveOnDispatcher() //make sure binding is on GUI thread
.Bind(out _EmployeeDetails) //bind to ReadOnlyObservableCollection bound to UI
//.DisposeMany() //necessary if Model is disposable
.Subscribe();
- updates moved from the dispatcher timer to an observable stream inside the view model
//actual updates timer
_SubscriptionToUpdatesPollingTimer = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(5))
.SubscribeOn(NewThreadScheduler.Default)
.ObserveOn(NewThreadScheduler.Default) // default test case
//.ObserveOnDispatcher() // <--------------------has no effect if the subscribe() is executed on UI thread
.Subscribe(_ =>
{
//executes every five seconds - fetch 20 items with max delay before update cancelled of 3 seconds
var updates = _RemoteService.FetchRemoteSimple(20)
//.ObserveOn(NewThreadScheduler.Default) //this can be observed on a separate thread or
//.ObserveOnDispatcher() // on GUI thread (if the parent observable is observed on dispatcher too
// the simpest case is no new thread
.Subscribe( newSnapshot =>
{
lock (_EmployeeDetailsCache)
{
var expiredItems = _EmployeeDetailsCache.Items.Where(old => !newSnapshot.Any(upd => upd.EmployeeId==old.EmployeeId));
_EmployeeDetailsCache.Edit(f =>
{
//remove expired and update items
f.Remove(expiredItems);
f.AddOrUpdate(newSnapshot);
});
/*
//tried the following one by one and all together
//1)
_EmployeeDetailsCache.Refresh();
//2)
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Render,
new Action(() =>
{
OnPropertyChanged("EmployeeDetails");
})
);
*/
}
});
});
which works with the underlying data source.
To see the exception, start dragging the row and dont let go (dont drop) until the grid has a row added or removed.
Running updates on dispatcher, including raising onpropertychanged event for the bound readonlycollection does not resolve this problem.
Thank you very much for looking into this issue.
Kind regards, AM
PS: This is the stack trace to show that the error happens in syncfusion and not in the dynamicdata:
> mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument argument, System.ExceptionResource resource) Line 93 C#
mscorlib.dll!System.Collections.Generic.List.this[int].get(int index) Line 178 C#
Syncfusion.Data.WPF.dll!Syncfusion.Data.RecordsListBase.GetRecord(int index) Unknown
Syncfusion.Data.WPF.dll!Syncfusion.Data.RecordsListBase.this[int].get(int index) Unknown
Syncfusion.SfGrid.WPF.dll!Syncfusion.UI.Xaml.Grid.GridRowDragDropController.DroppingItemsInDataGrid(Syncfusion.UI.Xaml.ScrollAxis.RowColumnIndex rowColumnIndex, Syncfusion.UI.Xaml.Grid.SfDataGrid sourceDataGrid, System.Windows.DragEventArgs args) Unknown
Syncfusion.SfGrid.WPF.dll!Syncfusion.UI.Xaml.Grid.GridRowDragDropController.ProcessOnDrop(System.Windows.DragEventArgs args, Syncfusion.UI.Xaml.ScrollAxis.RowColumnIndex rowColumnIndex) Unknown
Syncfusion.SfGrid.WPF.dll!Syncfusion.UI.Xaml.Grid.GridCell.GridCell_Drop(object sender, System.Windows.DragEventArgs e) Unknown
PresentationCore.dll!System.Windows.DragEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.OleDropTarget.RaiseDragEvent(System.Windows.RoutedEvent dragEvent, int dragDropKeyStates, ref int effects, System.Windows.DependencyObject target, System.Windows.Point targetPoint) Unknown
PresentationCore.dll!System.Windows.OleDropTarget.MS.Win32.UnsafeNativeMethods.IOleDropTarget.OleDrop(object data, int dragDropKeyStates, long point, ref int effects) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
...