.NET WPF binding


#1

Hi,

I’m developing an App on windows platform using C# with WPF. I can create a simple list and bind the data from realm.
Entries = realm.All<Item>();
where Entries is bound to a grid
This works fine until I changed to
Entries = realm.All<Item>().OrderBy(i => i.Timestamp);

the following exception will be thrown when I delete an item:
System.InvalidOperationException
HResult=0x80131509
Message=新增的項目未出現在指定的索引 ‘0’。
Source=PresentationFramework
StackTrace:
at MS.Internal.Data.EnumerableCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
at Realms.RealmCollectionBase1.RaiseCollectionChanged(NotifyCollectionChangedEventArgs args) at Realms.RealmCollectionBase1.OnChange(IRealmCollection1 sender, ChangeSet change, Exception error) at Realms.RealmCollectionBase1.Realms.NotificationsHelper.INotifiable.NotifyCallbacks(Nullable1 changes, Nullable1 exception)
at Realms.NotificationsHelper.NotificationCallbackImpl(IntPtr managedHandle, IntPtr changes, IntPtr exception)
at Realms.SynchronizationContextEventLoopSignal.EventLoop.<>c__DisplayClass3_0.b__0(Object _)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at WpfApp1.App.Main()


#2

Can you provide a simple project that reproduces the problem?


#3

Sure. I’m on Win 10 and VS2017


#4

Have you got the sample project? the link is going to expire soon


#5

Sorry for the delay - I was on vacation. I downloaded the project and played a little with it and it looks like the problem is that Realm emits a CollectionChanged event with Action = NotifyCollectionChangedAction.Remove and oldObject = null. Apparently, the WPF control that you’re using to visualize the collection doesn’t like that and it expects the object at the removed index (in its internal cache) to equal oldObject. Unfortunately, due to Realm’s architecture, it’s impossible to emit the event with the object reference the WPF control expects because that object has been deleted from the Realm and it simply no longer exists. There are two workarounds I can think of:

  1. Use a different WPF control that discards oldObject and just uses the index. This is by far the easiest solution as it doesn’t require changes in the Realm SDK.
  2. Figure out some hack that would fake equality between an invalid (deleted) RealmObject instance and null.