In the constructor of XamPropertyGrid, it looks like there is a call to add an event handler to a static event (TypeDescriptor.Refreshed).
IE. I can put a breakpoint in the debugger and I see this method call:
System.ComponentModel.TypeDescriptor.add_Refreshed
There is never an equivalent call to release/unsubscribe from that event handler.
The result is that my app has a very rapid leak. Below is an image of the path to the rooted reference. I suppose I may have to do manual cleanup to remove the XamPropertyGrid control from my ProductDetailsControl as a workaround. But even then it will still have a leak of the XamPropertyGrid instances themselves...
Can anyone suggest any easy workarounds?
Hello David,
It appears that this forum thread is essentially a duplicate to a private support case that you submitted that I have very recently answered and logged a development issue for. I will post a summary transcript of the answer I posted to the support case below:
I have been investigating into the sample project you have provided, and I have reproduced this issue. The workaround to this would normally be to either derive a custom XamPropertyGrid and use reflection to get the event handler for TypeDescriptor.Refreshed to unhook it when the XamPropertyGrid is unloading, but this unfortunately won't work, and I cannot recommend a known workaround for this. The reason it will not work is because of the way this event is hooked in our source code – it is using an anonymous lambda expression event handler, and so I cannot get it using reflection. It is hooked like so:
TypeDescriptor.Refreshed += (e) => { this.PropertyDescriptorCollectionCache.Clear(); };
This is unexpected behavior, and as such, I have asked our engineering staff to examine it further. To ensure that it will receive attention, I have logged this behavior in our internal tracking system with a Development ID of 262191. The next step will be for a developer to review my investigation and confirm my findings or to offer a fix, or other resolution.
It is also worth noting that version 2017.2 has had its final service release, and so this issue will not be fixed in 2017.2. Actually, the earliest version that this will be fixed in will actually be 2018.2, as the final 2018.1 service release has been finalized as of yesterday and is now undergoing testing. You can see this from the product lifecycle page, here: https://ko.infragistics.com/support/product-lifecycle.
Please let me know if you have any other questions or concerns on this matter.
Yes, thanks Andrew. I wanted to also post the problem (and eventual resolution) in the open forum. I didn't find any mention of it yet, and this issue would presumably affect every WPF customer using the XamPropertyGrid.
I always like to see problems being solved out in the open. If a google search can give a quick answer to a problem like this one, then it is easy to save some other developer a lot of time (days/weeks) that they might otherwise be interacting with tech support.
... I know there have been many times that I've been able to benefit from public information about well-known bugs (whether in third-party forums or KB's or blogs or whatever).
Thank you for your update on this matter. It makes sense that you want to make mention of this and have it resolved out in the open.
Regarding actually accessing the XamPropertyGridAutomationPeer, I’m unsure how you can actually access these, as there isn’t a collection that I can see, and the XamPropertyGridAutomationPeer is effectively just a FrameworkElementAutomationPeer. As such, if there is a way to get the automation peers from a simple FrameworkElement, I would expect you could get it from the XamPropertyGrid the same way.
I believe the best thing I could recommend in this case if you don’t actually need the automation and want to shut it off, you could derive a custom XamPropertyGrid and override OnCreateAutomationPeer and return null from this method. This should remove it from memory completely, as they simply won’t be created, and it would resolve this issue you are seeing.
Hi Andrew, I had started down the path you described. Now my path to root is still related to automation, but it appears to be slightly different in that it is related to the scrollbar.
See screenshot. Note that the "XamFastPropertyGrid" is basically a XamPropertyGrid whose OnCreateAutomationPeer returns null.
This UI automation stuff is very troublesome. I wish you could tell me how to override the behavior so that all controls in my application would ignore it altogether.
Any ideas how I can break apart these new paths to root that pass thru the "ScrollBarInfoMediator" and the "ScrollBarAutomationPeer"?
Thank you for your update. I have recently answered the internal support case that we have together that is linked to development issue 262191. That response refers to this forum thread, and I will post a transcript of that response below:
"I am a little confused in this case, as on the forum thread that we have together, you mentioned you were able to come up with a workaround that disconnects the XamPropertyGrid from the parent ProductDetailsControl and now are seeing issues with a ScrollBarInfoMediator and a ScrollBarAutomationPeer. We have no control over the creation of the ScrollBarAutomationPeer, as this is likely being done by the vertical scrollbar, which is a WPF-built in ScrollBar element and it is creating its own automation peer.
I am currently working toward trying to get to the point that you are seeing, as I have tried to disconnect the XamPropertyGrid from the parent ProductDetailsControl, but I am still seeing the same root in memory – that is, the RefreshEventHandler for TypeDescriptor.Refreshed.
That said, while I have not been able to test things out on my end to see if this would work, I did come up with a way that you can get to the ScrollBarInfoMediator and set it to null. It is hacky and I was only able to test this such that it doesn’t throw an exception when run, but it may help you to disconnect the ScrollBarInfoMediator, where “propGrid” is your local XamPropertyGrid:
FieldInfo info = typeof(XamPropertyGrid).GetField("_scrollBarInfoMediator", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var x = info.GetValue(propGrid); info.SetValue(propGrid, null);"
In the private support case, I attached a modified version of the sample project that you had provided. I won’t be attaching it here (yet) in the case that you do not want it publicly visible.
Sincerely, Andrew Goldenbaum Software Developer
I'm following your lead, and I'm setting a variety of private member fields to null on the XamPropertyGrid. It seems that UI automation is causing my ProductDetailsControl to be rooted via *all* of the following private fields on XamPropertyGrid:
_scrollBarInfoMediator_propertyGridFilterAreaControl_columnResizeThumb_itemLayoutPanel_flatItemList
I've set them all to null, including the field, _propertyGridFilterAreaControl. However, that particular one is still appearing in my paths to root on ProductDetailsControl. I think it is because of a control template or something like that. See image below. Notice that there are a few levels of indirection between the XamPropertyGrid and the PropertyGridFilterAreaControl.
This is starting to feel a little hopeless. It is too difficult to tear this XamPropertyGrid out of the visual tree!
It is interesting that the PropertyGridFilterAreaControl is still hanging on to the XamPropertyGrid in this case, but I think you are right that this could be coming from the underlying ControlTemplate of the XamPropertyGrid, as the PropertyGridFilterAreaControl is certainly a part of that template.
You can get at the PropertyGridFilterAreaControl from the XamPropertyGrid by using the Infragistics.Windows.Utilities class and its GetDescendantFromName method, like so, where “propGrid” is your local XamPropertyGrid:
var filterAreaControl = Infragistics.Windows.Utilities.GetDescendantFromName(propGrid, “PART_PropertyGridFilterAreaControl”);
This PropertyGridFilterAreaControl has a parent Grid element, and perhaps removing it from its Grid.Children could help to release it?
As a side note, I have received a comment from someone on our development team here regarding the automation peers. Rather than returning null from the OnCreateAutomationPeer element, they have recommended to create a new automation peer derived from FrameworkElementAutomationPeer and return it. In your new automation peer, you can override the GetChildrenCore method and return an empty list, as this would explicitly tell it to return no children.
For anyone else that encounters this bug, it appears to be fixed.
The rooting of the XamPropertyGrid is not happening in Infragistics WPF 2018 Vol. 2 - Service Release 20182.281.
Thank you for your update on this matter.
I do not personally have much experience with the Citrix environment myself, and so I’m not sure I would really be able to provide much information on how the actual UI Automation works there. That said, I was able to reproduce this is a simple WPF-application without the Citrix environment, and so I would expect that this particular issue is related to that and not Citrix, specifically.
Regarding the bug, I don’t think there is much of a doubt that this rooting is a bug, as the issue seems to be that there is an event handler that is never unhooked. As far as an ETA, though, I do not currently have one, as the bug is not yet assigned to a developer and is in an “In Review” state. At the time of writing this, the upcoming (and final) service release for version 2018.1 is finalized and we are in a “code-frozen” state so that we can accurately perform our automated testing, but if you would like, I can see about getting this issue escalated to an upcoming bi-weekly build or the following service release?
Please let me know how you would like to proceed.
Thanks for the tip about the automation peers. I should probably know more about this stuff. Unfortunately I never enable it (accessibility) on my desktop.
I should point out that I don't enable it in Citrix either ... but it seems to be auto-enabled as a component of some funky Citrix monitoring agent. At least that is what I've been able to gather. The frustration I have with Citrix is that the members of those community forums rarely understand how their stuff works internally, and you can never get answers to questions that are technical. In order to get a WPF application to work properly in Citrix, it simply involves endless "trial-and-error". That's not how I'd prefer to spend my software development hours.
Since you were speaking with Infragistics development, have they acknowledged that the rooting of this control is a bug? Is there any approximate ETA yet on a fix?