16

I am not new to WPF, but I can't figure out this problem:

I use an ObservableCollection<MyCustomType> that i bind to ComboBoxes, it's all working great as usual, but at some point i need to change the content of the collection (i retrieve a new set from the database, that may or may not contain part of the old one).

Now adding or removing elements is all done by WPF, but if you change the whole collection I found you had to raise PropertyChanged for the collection.

The problem is that sometimes it crashes giving me a not-so-friendly exception.
I'm unsure of what exactly triggers the crash, but if I don't touch the View and retrieve a new set from DB, it doesn't crash.

Here is some code:

    public const string MyObsCollectionProperty = "MyObsCollection";
    private ObservableCollection<MyCustomType> m_MyObsCollection;
    public ObservableCollection<MyCustomType> MyObsCollection
    {
        get { return m_MyObsCollection; }
        set
        {
            m_MyObsCollection = value;
            RaisePropertyChanged(MyObsCollectionProperty); // <-- Crashes here
        }
    }

I get the exception: Unable to cast object of type 'MS.Internal.NamedObject' to type 'MyNameSpace.MyCustomType'

Please note that this exception comes from Prism, but it's probably just because i inherit from NotificationObject on my ViewModel.

I appreciate any help on this problem,

Regards,

LK.

EDIT: I think the problem comes from the ComboBox, and more specifically, from the way i set their properties.

I bind the ItemsSource property to an ObservableCollection, and to decide which element to select, I bind the SelectedValue to a field of an item of an ObservableCollection (the ComboBox is nested within a ListView).
I also set SelectedValuePath (you get the idea).

I guess when i change the first collection hell breaks lose on that setup. And it leaves it in peace when i don't touch the view because of virtualization (it is hidden at first).

ADDITION:

The InnerException is nulll.

Message: Unable to cast object of type 'MS.Internal.NamedObject' to type 'CocoonV4.DAL.WcfServiceCocoonV4.DekoTemplate'.

   at Microsoft.Practices.Prism.Commands.DelegateCommand`1.<>c__DisplayClass6.<.ctor>b__3(Object o)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.CanExecute(Object parameter)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.CanExecute(Object parameter)
   at System.Windows.Interactivity.InvokeCommandAction.Invoke(Object parameter)
   at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter)
   at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs)
   at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs)
   at System.Windows.Controls.SelectionChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.ComboBox.OnSelectionChanged(SelectionChangedEventArgs e)
   at System.Windows.Controls.Primitives.Selector.InvokeSelectionChanged(List`1 unselectedItems, List`1 selectedItems)
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
   at System.Windows.Controls.Primitives.Selector.OnItemsChanged(NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.ItemsControl.OnItemCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e)
   at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.ListCollectionView.RefreshOverride()
   at System.Windows.Data.CollectionView.RefreshOrDefer()
   at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.ClearItems()
   at System.Collections.ObjectModel.Collection`1.Clear()
   at CocoonV4.Modules.CocoonViewsVMs.ManageTemplateDekocastViewModel.SetAllowedDekos(IEnumerable`1 _NewAllowedDekos) in C:\Users\lkottmann\Documents\Visual Studio 2010\Projects\IAV-Cocoon\MAIN\CocoonV4\CocoonV4.Modules.RunningItem\CocoonViewsVMs\ManageTemplateDekocastViewModel.cs:line 83
   at CocoonV4.Modules.CocoonViewsVMs.ManageTemplateDekocastViewModel.LoadTemplates(Nullable`1 param) in C:\Users\lkottmann\Documents\Visual Studio 2010\Projects\IAV-Cocoon\MAIN\CocoonV4\CocoonV4.Modules.RunningItem\CocoonViewsVMs\ManageTemplateDekocastViewModel.cs:line 128
   at Microsoft.Practices.Prism.Commands.DelegateCommand`1.<>c__DisplayClass6.<.ctor>b__2(Object o)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.Execute(Object parameter)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.Execute(Object parameter)
   at System.Windows.Interactivity.InvokeCommandAction.Invoke(Object parameter)
   at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter)
   at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs)
   at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs)
   at System.Windows.Controls.SelectionChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.ComboBox.OnSelectionChanged(SelectionChangedEventArgs e)
   at System.Windows.Controls.Primitives.Selector.InvokeSelectionChanged(List`1 unselectedItems, List`1 selectedItems)
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.SelectJustThisItem(Object item, Boolean assumeInItemsCollection)
   at System.Windows.Controls.ComboBox.NotifyComboBoxItemMouseUp(ComboBoxItem comboBoxItem)
   at System.Windows.Controls.ComboBoxItem.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(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 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(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 CocoonV4.App.Main() in C:\Users\lkottmann\Documents\Visual Studio 2010\Projects\IAV-Cocoon\MAIN\CocoonV4\CocoonV4\obj\x86\Debug\App.g.cs:line 0
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

More EDIT:

I isolated the problem to a single ComboBox declarated as follow:

<custom:CComboBox x:Name="cmbFirstDko"
                  ItemsSource="{Binding Path=DataContext.MyFirstCollection, ElementName=myViewName}"
                  SelectedValue="{Binding anObjectID, Mode=TwoWay}"
                  SelectedValuePath="anObjectID">

Please note that the anObjectID property in SelectedValue comes from the ListView's DataContext (this ComboBox is displaying part of an item of that ListView), whereas the anObjectID in SelectedValuePath refers to a property that each item in DataContext.MyFirstCollection has.

This allows me to select a different ComboBoxItem for each element of the ListView.

I hope my explanation is clear, otherwise tell me in the comments and i'll try to clarify.

Breakthrough: The ComboBoxes have their DataContext set to {DisconnectedItem}, this is the result of the work of so-called SentinelObjects which intervene when there's a binding between 2 collections, as in my example.

It is actually officialy a bug of the framework, and it has been fixed for the next version, see this MS Bug Page

Does anyone know of a workaround?

EDIT: There used to be an answer linking to my blog, but while I move it people downvoted the answer. I got sick of it so now it'll be back when it's ready.

Louis Kottmann
  • 16,268
  • 4
  • 64
  • 88
  • I wouldn't recommend a setter on `ObservableCollection` properties, i usually use a `readonly` field and a property with only a getter. – H.B. Nov 22 '11 at 12:52
  • Can you post how this RaisePropertyChanged is implemented? Why isn't it taking a string? – MBen Nov 22 '11 at 12:52
  • @MBen: MyObsCollectionProperty is a string. – H.B. Nov 22 '11 at 12:54
  • @H.B. How do you deal with my scenario then? You clear the collection then add all fields from the new set? – Louis Kottmann Nov 22 '11 at 12:58
  • Sorry didn't see that. Well check if the Value you are setting (m_MyObsCollection = value;) is the correct type, it seems you are passing a MS.InternalNamedObject instead of MyCustomType... – MBen Nov 22 '11 at 13:01
  • I just checked, it recieves the correct type. Besides, if it didn't, (m_MyObsCollection = value;) would crash, not the RaisePropertyChanged. I suspect it has something to do with the ComboBoxes – Louis Kottmann Nov 22 '11 at 13:05
  • Huum interesting, can't tell like this without some more code about you are binding the ComboBox and such. – MBen Nov 22 '11 at 13:08
  • @Baboon: Yes, you `Clear()` and `Add()`. – H.B. Nov 22 '11 at 13:16
  • @MBen and H.B, I updated the question, I believe it is because of the ComboBox setup. – Louis Kottmann Nov 22 '11 at 13:25
  • @H.B. I change to your practice, it does look better, but it doesn't solve the problem (same exception, but on the Clear() line). – Louis Kottmann Nov 22 '11 at 13:26
  • @Baboon What a nice stack trace for someone who just started learning WPF! Can't be better :) Are you using CollectionViewSource anywhere in your view? –  Nov 22 '11 at 14:48
  • @Dmitry no i don't use it anywhere. – Louis Kottmann Nov 22 '11 at 14:53
  • I updated the question with additional information. – Louis Kottmann Nov 22 '11 at 15:23
  • Are you forced to uise ObservableCollection - can you use just List? Do you use CollectionChanged event handler at all? –  Nov 22 '11 at 15:50
  • I need the ObservableCollection if I want to keep it clean as H.B. suggested. Besides, my problem actually comes from the gloomy SentinelObjects... – Louis Kottmann Nov 22 '11 at 16:30
  • I see that error in PRISM when I try to use a `DelegateCommand`, and the value passed as the `CommandParameter` can't be parsed to ``. Do you have a `DelegateCommand` anywhere that is getting executed? Or that raises it's `CanExecuteChanged()` when your collection changes? – Rachel Nov 22 '11 at 16:59
  • Yes, the line of code that is executed is within a function called by a DelegateCommand. However, my problem seems to come from the ComboBoxes having their DataContext set to {DisconnectedItem}. I'll update the question again with this new information. – Louis Kottmann Nov 22 '11 at 17:24
  • I finally found a "clean" solution... I'll write a blog post and link it here in a few days. Crazy shit... – Louis Kottmann Nov 23 '11 at 13:02

2 Answers2

2
  1. No need to call RaisePropertyChanged for MyObsCollection, because ObservableCollection internal implements INotifiyProperty Changed.
  2. I think it is Crashing while assign the value(during set call), this will happen when you try to assign a collection of one type collection of another type. You have to create object of the MyCustomType and should be added to the MyObsCollection instead of directly assigning a collection of different type to MyObsCollection

It would be great if could post the entire code or piece of code where u assign the or add objects to MyObsCollection

Kumareshan
  • 1,311
  • 8
  • 8
2

I've the same problem just now, and after I remove the static-ressource Style on the ItemContainerStyle and define it directly beneath ListBox, the problem went away.

I had x:Name property on the elements in DataTemplate, and since I deleted them, the compilator didn't make it at all, probably. So I changed a way at all to make it sense.

Hope this small trick will help you !

Yang C
  • 536
  • 5
  • 16