1
votes

We've used WPF Toolkit DataGrid and .NET 4.0 for about 1.5 years. And some times we've got exception - "Recursive call to Automation Peer API is not valid" on some of the client PC's, other Users are not having this issue.

We have used WPF Toolkit DataGrid with Template Column, which the cell template has a check box (WPF Toolkit DataGrid as CheckBox content control). Also we have used the context menu in this grid.

Type : System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Recursive call to Automation Peer API is not valid.
Source : PresentationCore
Help link : 
Data : System.Collections.ListDictionaryInternal
TargetSite : System.Collections.Generic.List`1[System.Windows.Automation.Peers.AutomationPeer] GetChildren()
HResult : -2146233079
Stack Trace :    at System.Windows.Automation.Peers.AutomationPeer.GetChildren()
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.ValidateConnected(AutomationPeer connectedPeer)
   at MS.Internal.Automation.ElementProxy.StaticWrap(AutomationPeer peer, AutomationPeer referencePeer)
   at System.Windows.Automation.Peers.AutomationPeer.UpdateChildrenInternal(Int32 invalidateLimit)
   at System.Windows.Automation.Peers.AutomationPeer.UpdateChildren()
   at System.Windows.Automation.Peers.AutomationPeer.ResetChildrenCache()
   at Microsoft.Windows.Automation.Peers.DataGridItemAutomationPeer.GetChildrenCore()
   at System.Windows.Automation.Peers.AutomationPeer.EnsureChildren()
   at System.Windows.Automation.Peers.AutomationPeer.GetChildren()
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.ValidateConnected(AutomationPeer connectedPeer)
   at System.Windows.Automation.Peers.AutomationPeer.AutomationPeerFromInputElement(IInputElement focusedElement)
   at System.Windows.Automation.Peers.AutomationPeer.RaiseFocusChangedEventHelper(IInputElement newFocus)
   at System.Windows.Input.KeyboardDevice.ChangeFocus(DependencyObject focus, Int32 timestamp)
   at System.Windows.Input.KeyboardDevice.TryChangeFocus(DependencyObject newFocus, IKeyboardInputProvider keyboardInputProvider, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
   at System.Windows.Input.KeyboardDevice.Focus(DependencyObject focus, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
   at System.Windows.Input.KeyboardDevice.Focus(IInputElement element)
   at System.Windows.Interop.HwndKeyboardInputProvider.OnSetFocus(IntPtr hwnd)
   at System.Windows.Interop.HwndKeyboardInputProvider.FilterMessage(IntPtr hwnd, WindowMessage message, 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)

Let us know the solution for same or suggest if anything we are doing wrong.

2

2 Answers

2
votes

I have solved this problem using the lower version of WPFToolkit. Earlier I am using the WPFToolkit v3.5.50211.1 which was causing the problem. Now I am using the lower version v3.5.40619.1 to solve the issue.

In WPFToolkit v3.5.50211.1 one bug is fixed related to UI Automation and I guess because of that this automation peer issue is coming while using the latest WPFtoolkit.

check related links-

WPF Recursive call to Automation Peer API is not valid

0
votes

This has been asked before on stackoverflow but it was never resolved.

When I looked through the code, it looks like it is caused by something that could be modifying the collection as the collection is being enumerated forcing a fresh enumeration that isn't possible whilst the original enumeration is already occurring. This is due to a framework level protection in the Automation Peer code.

Trying to found out how and why it occurs could be very tricky unless you have included code that logs when the collection is modified and manage to successfully debug that. One solution may be to make sure that all collection modifications occur only on the GUI thread though that could lead to UI blocking if you have a large amount.

However, that is all just speculation. Personally, I have never had it in any of the code that I have so if you have sample code that can successfully reproduce this I would gladly try and take a look.

Potential fix

I forgot to mention that some people have suggested that a potential fix is to override the template by adding:

protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
    // Create your own AutomationPeer  
    // return new MyAutomationPeer(this);
    // or return null if you don't need it
    return null;
}

How effective this is, and whether it removes any functionality since it's basically saying you don't have a peer, is unknown to me.

(see this MSDN Forum post)