Mik*_*scu 13 wpf datagrid windows-8
我正在使用一个奇怪的NullReferenceException,它显然是从ItemAutomationPeer类的GetNameCore()函数触发的.
下面的例外细节如下,但真正有趣的方面是它不会出现在运行Windows 7的开发机器或我们测试过的其他Windows 7计算机上.它只发生在我的Windows 8 Pro测试机上.
尝试编辑WPF DataGrid控件中的单元格时,显然会抛出异常.
我一直试图追踪它整天没有成功.我尝试使用Visual Studio远程调试进程并单步执行代码,但是没有任何用户代码似乎触发异常.它显然是由PresentationFramework.Dll内部的一系列事件执行的,异常只是通过AppDomain冒泡并最终导致应用程序崩溃.
如果任何人可以想到任何可能导致这种情况的事情,或者某种方法来解决它,那将非常有帮助.
Exception Type: System.NullReferenceException
Exception Message: Object reference not set to an instance of an object.
Method Information: System.String GetNameCore()
Exception Source: PresentationFramework
Stack Trace
at System.Windows.Automation.Peers.ItemAutomationPeer.GetNameCore()
at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
at System.Windows.ContextLayoutManager.fireAutomationEvents()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(Object resizedCompositionTarget)
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.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
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 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 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, 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.Threading.Dispatcher.Run()
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()
Run Code Online (Sandbox Code Playgroud)
Mik*_*scu 14
经过远程调试器的大量反复,以及几乎无效的在线搜索后,我能够将问题追溯到几个行为不端的ItemAutomationPeer实例.
当我遇到这个问题时,我对UI自动化及其在WPF框架中的支持方面缺乏了解.实际上,当AutomationPeer由于某种原因让我想到COM互操作时,我一时间追错了问题.如果您正在阅读本文并且不知道UI Automation可能从这里开始,这里可能会让您了解UI自动化在WPF上下文中的含义.
在我的情况下,事实证明应用程序崩溃在Windows 8测试机器上但它在我的开发机器(以及它已被部署到的无数其他计算机上)正常工作的原因是Windows 8机器有一些运行的UI辅助功能应用程序(或其他一些UI自动化客户端).一旦我在Windows 7开发机器上启动了Narrator应用程序,我就能让应用程序崩溃一样.
一旦我理解了根问题,我仍然无法进一步调试这个以确切地找出导致问题的控件,但更多在线阅读似乎指向自定义控件的大致方向,所以我开始了一个消除过程以确定哪个自定义WPF控件是有罪的.我找到了两个自定义控件 - 一个扩展了DataGrid,另一个扩展了ListBox.
最后,我的问题的解决方案是创建自定义类,扩展ItemsControlAutomationPeer基类,并通过覆盖OnCreateAutomationPeer方法在每个自定义控件上提供这些自定义控件.
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ControlSpecificCustomAutomationPeer(this);
}
Run Code Online (Sandbox Code Playgroud)
ControlSpecificCustomAutomationPeer类可能至少看起来像这样:
public class ControlSpecificCustomAutomationPeer
: ItemsControlAutomationPeer
{
public ControlSpecificCustomAutomationPeer(ItemsControl owner)
: base(owner)
{
}
protected override string GetNameCore()
{
return ""; // return something meaningful here..
}
protected override ItemAutomationPeer CreateItemAutomationPeer(object item)
{
return new CustomDummyItemAutomationPeer(item, this);
}
}
public class CustomDummyItemAutomationPeer
: System.Windows.Automation.Peers.ItemAutomationPeer
{
public CustomDummyItemAutomationPeer(object item, ItemsControlAutomationPeer itemsControlAutomationPeer)
: base(item, itemsControlAutomationPeer)
{
}
protected override string GetNameCore()
{
if (Item == null)
return "";
return Item.ToString() ?? "";
}
protected override AutomationControlType GetAutomationControlTypeCore()
{
return System.Windows.Automation.Peers.AutomationControlType.Text;
}
protected override string GetClassNameCore()
{
return "Dummy";
}
}
Run Code Online (Sandbox Code Playgroud)