为啥 WPF 将我的数据上下文设置为 MS.Internal.NamedObject?
Posted
技术标签:
【中文标题】为啥 WPF 将我的数据上下文设置为 MS.Internal.NamedObject?【英文标题】:Why is WPF setting my data context to MS.Internal.NamedObject?为什么 WPF 将我的数据上下文设置为 MS.Internal.NamedObject? 【发布时间】:2013-11-07 00:40:25 【问题描述】:我有一个程序在 .NET 4.0 / Windows 7 上崩溃,但在 .NET 4.5 / Windows 8+ 上运行良好。销毁控件时(例如,通过关闭控件所在的窗口),WPF 似乎试图将 DataContext
设置为 MS.Internal.NamedObject
类型的对象——这失败了,因为控件总是期望数据上下文是与该视图配套的视图模型:
System.InvalidCastException:无法将“MS.Internal.NamedObject”类型的对象转换为“Foo.Bar.BazViewModel”类型。
这里发生了什么?我可以要求 WPF 不要像这样弄乱数据上下文,还是应该在发生这种情况时禁用控件?
【问题讨论】:
Can I ask WPF to not...
- 不,你不能强迫 WPF 满足你的意愿。更正您拥有的任何有问题的代码。如果将 UI 元素的 DataContext
设置为任何对象,也不应在任何意外情况下,UI 元素不应使整个应用程序崩溃。更正您的代码。
@HighCore:没有任何地方证明 WPF 保留从控件下方更改 DataContext
的权利。
上下文...您究竟是如何销毁控件?
@OmegaMan:用户关闭控件所在的窗口。
@BillyONEal 您可以继续尝试用木刀穿透铁墙(并想知道为什么没有记录任何木头不能破坏铁的地方),或者您可以更正有问题的代码。应该是if (DataContext is MyViewModel)
的问题......事情就是这样。顺便说一句,即使 WPF 没有这样做,您也会在您的应用程序中创建潜在的崩溃,这很糟糕。如果需要,UI 元素应该“期望”特定的 ViewModel,但如果传递了不同的 ViewModel / DataContext,它们永远不会崩溃。
【参考方案1】:
其他事情正在发生。
我建议创建一个独立的示例,该示例能够代表结构、绑定和提炼为最基本形式的数据。如果该问题可以在独立项目中重现,那么您可能有一个应该报告给Microsoft Connect 的错误。
示例项目更有可能揭示导致情况的差异,从而使您能够解决问题。或者至少将其发布到 Stack Overflow 并让答案鲨鱼享用新鲜的示例杀戮;可以这么说。
异步数据操作可能来得太晚了。检查是否有任何可能被关闭的帖子更新。
【讨论】:
我强烈怀疑这是在 .NET 4.5 和/或 Win8 中修复的某种错误。 @BillyONEal 程序是在 4 上编写然后移植到 4.5 还是反之亦然? 正在 Win8 和/或 8.1 机器上进行开发,.NET 4.5,目标平台设置为 .NET 4.0。直到客户尝试在安装了 .NET 4.0(仅)的 Win7 计算机上运行该应用程序后,问题才出现。不管是操作系统还是 .NET 版本,都没有用完。【参考方案2】:我不确定这是否是同一个问题,但对于它的价值,我还遇到了一个奇怪的问题,WPF 会为ItemsControl
中的每个视图对象调用我的DataContextChanged
处理程序。当我将远程桌面连接到运行应用程序的服务器时,就会发生这种情况——但我无法在我的机器或任何其他机器上重现它。不知何故,我发现了根本原因:当当前的 Windows 7 主题从 Aero 更改为 Classic(或反之亦然)时,ItemsControl
中每个对象的DataContext
将设置为MS.Internal.NamedObject
(但不会被破坏) .我通过将配色方案从 Classic 更改为 Basic 暂时回避了这个问题,这防止了在 RDP 登录时发生这种现象。对于我的应用程序正在运行并且用户确实更改了主题的情况,我修改了我的处理程序方法以在 DataContext
不是预期类型时返回。然而,即便如此,现在集合中的所有视图项都有双倍。每次主题更改时,都会创建另一组完整的实例(每个“组”的最新实例具有 WPF 设置的正确数据上下文;其余的都是孤立的)
【讨论】:
以上是关于为啥 WPF 将我的数据上下文设置为 MS.Internal.NamedObject?的主要内容,如果未能解决你的问题,请参考以下文章