无法将类型为“MS.Internal.NamedObject”的对象转换为自定义类型

16

我对WPF并不陌生,但是我无法解决这个问题:

我使用一个ObservableCollection & lt; MyCustomType & gt;,将其绑定到ComboBox,一切都像往常一样运作良好,但在某些时候,我需要更改集合的内容(我从数据库中检索一个新的数据集,其中可能包含部分旧的数据集)。

现在,如果添加或删除元素,都是由WPF完成的,但是如果更改整个集合,我发现您必须为该集合引发PropertyChanged。

问题是有时会崩溃,并给出一条不太友好的异常信息。
我不确定到底是什么导致了崩溃,但如果我不触摸视图并从DB检索新的数据集,则不会崩溃。

以下是一些代码:

    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
        }
    }

我遇到了异常:无法将类型为'MS.Internal.NamedObject'的对象强制转换为类型'MyNameSpace.MyCustomType' 请注意,这个异常来自Prism,但可能只是因为我在ViewModel上继承了NotificationObject。
非常感谢您对此问题的任何帮助,
问候,
LK。
编辑:我认为问题来自ComboBox,更具体地说,来自我设置它们属性的方式。
我将ItemsSource属性绑定到ObservableCollection,并将SelectedValue绑定到ObservableCollection的项目字段中的字段(ComboBox嵌套在ListView中)以决定选择哪个元素。 我还设置了SelectedValuePath(你知道的)。
我猜当我改变第一个集合时,这个设置会出现问题。当我不触摸视图时,由于虚拟化(它一开始是隐藏的),它会保持安静。
添加:
InnerException为空。
消息:无法将类型为'MS.Internal.NamedObject'的对象强制转换为类型'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()

更多编辑:

我把问题隔离到了一个单独的ComboBox,声明如下:

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

请注意,SelectedValue中的anObjectID属性来自ListView的DataContext(此ComboBox正在显示该ListView的项目的一部分),而SelectedValuePath中的anObjectID是指DataContext.MyFirstCollection中每个项目都有的属性。
这使我可以为ListView的每个元素选择不同的ComboBoxItem。
我希望我的解释很清楚,否则请在评论中告诉我,我会尽力澄清。
突破:
ComboBoxes的DataContext设置为{DisconnectedItem},这是所谓的SentinelObjects的工作结果,它们在两个集合之间存在绑定时进行干预,就像我的例子一样。
实际上,这实际上是一个框架的错误,并已经为下一个版本进行了修复,请参见MS Bug Page 有人知道解决方法吗?
编辑:
曾经有一个回答链接到我的博客,但当我移动它时,人们对回答进行了投票。我受够了,所以现在它准备好了就会回来。

我不建议在ObservableCollection属性上使用setter,通常我会使用一个只有getter的readonly字段和属性。 - H.B.
@MBen:MyObsCollectionProperty 是一个字符串。 - H.B.
抱歉,没有看到那个。请检查您正在设置的值(m_MyObsCollection = value;)是否为正确的类型,似乎您传递了一个 MS.InternalNamedObject 而不是 MyCustomType... - MBen
@MBen和H.B,我更新了问题,我相信这是因为ComboBox的设置。 - Louis Kottmann
@H.B. 我按照你的做法改了,看起来确实更好,但是它并没有解决问题(相同的异常,但在Clear()行上)。 - Louis Kottmann
显示剩余13条评论
2个回答

2

我刚刚也遇到了同样的问题,当我在ItemContainerStyle中删除静态资源Style并直接在ListBox下定义它时,问题消失了。

我在DataTemplate中的元素上有x:Name属性,但是自从我删除它们后,编译器完全没有将其编译,可能是因为这个原因。所以我改变了一种方法来使它有意义。

希望这个小技巧能帮到你!


2
  1. 不需要为MyObsCollection调用RaisePropertyChanged,因为ObservableCollection内部实现了INotifyPropertyChanged。
  2. 我认为在赋值时(在set调用期间)会崩溃,当您尝试将一个类型的集合分配给另一个类型的集合时,就会发生这种情况。您必须创建MyCustomType的对象,并将其添加到MyObsCollection中,而不是直接将不同类型的集合分配给MyObsCollection。

如果您能够发布整个代码或分配对象到MyObsCollection的代码片段,那就太好了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接