我对WPF并不陌生,但我无法解决这个问题:
我使用ObservableCollection<MyCustomType>
我绑定(bind)到ComboBox
es,一切都像往常一样工作得很好,但在某些时候我需要更改集合的内容(我从数据库中检索一组新集合,它可能包含也可能不包含旧集合的一部分)。
现在添加或删除元素都是由 WPF 完成的,但如果您更改整个集合,我发现您必须为集合引发 PropertyChanged。
问题是有时它会崩溃,给我一个不太友好的异常。
我不确定到底是什么触发了崩溃,但如果我不触摸 View 并从数据库检索新的集合,它就不会崩溃。
这是一些代码:
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
}
}
我得到异常:Unable to cast object of type 'MS.Internal.NamedObject' to type 'MyNameSpace.MyCustomType'
请注意,此异常来自 Prism,但这可能只是因为我从 ViewModel 上的 NotificationObject 继承。
感谢您对这个问题的任何帮助,
问候,
LK。
编辑:我认为问题来自 ComboBox,更具体地说,来 self 设置其属性的方式。
我将 ItemsSource 属性绑定(bind)到 ObservableCollection,为了决定选择哪个元素,我将 SelectedValue 绑定(bind)到 ObservableCollection 的项目的字段(ComboBox 嵌套在 ListView 中)。
我还设置了 SelectedValuePath (你明白了)。
我想当我更改第一个集合时,该设置就会失败。当我因为虚拟化而不触摸 View 时,它会保持平静(它最初是隐藏的)。
添加:
InnerException 为空。
消息: 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()
更多编辑:
我将问题隔离到单个 ComboBox 中,声明如下:
<custom:CComboBox x:Name="cmbFirstDko"
ItemsSource="{Binding Path=DataContext.MyFirstCollection, ElementName=myViewName}"
SelectedValue="{Binding anObjectID, Mode=TwoWay}"
SelectedValuePath="anObjectID">
请注意anObjectID
属性(property) SelectedValue
来自ListView
的 DataContext(此 ComboBox 正在显示该 ListView 的项目的一部分),而 anObjectID
在SelectedValuePath
指 DataContext.MyFirstCollection
中每一项的属性有。
这允许我为 ListView 的每个元素选择不同的 ComboBoxItem。
我希望我的解释很清楚,否则请在评论中告诉我,我会尽力澄清。
突破: ComboBox 将其 DataContext 设置为 {DisconnectedItem},这是所谓的 SentinelObjects 工作的结果,当两个集合之间存在绑定(bind)时,它会进行干预,如我的示例中所示。
这实际上是框架的官方错误,已在下一个版本中修复,请参阅此 MS Bug Page
有人知道解决方法吗?
编辑: 曾经有一个答案链接到我的博客,但是当我移动它时,人们对答案投了反对票。我已经厌倦了它,所以现在它准备好了就会回来。
最佳答案
- 无需为 MyObsCollection 调用 RaisePropertyChanged,因为 ObservableCollection 内部实现了 INotifiyProperty Changed。
- 我认为分配值时(在设置调用期间)会崩溃,当您尝试分配另一种类型的一种类型集合的集合时,就会发生这种情况。您必须创建 MyCustomType 的对象,并将其添加到 MyObsCollection,而不是直接将不同类型的集合分配给 MyObsCollection
如果可以发布整个代码或将对象分配或添加到 MyObsCollection 的代码段,那就太好了
关于wpf - 无法将类型 'MS.Internal.NamedObject' 的对象转换为自定义类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8227083/