Our app has a property grid in a tab control, with other controls in other tabs. Recently we added code to remember which tab was selected when the user closes the window containing the tab control, and restore selection next time it is opened. This seems to be causing some memory leaks because PropertyDescriptor.RemoveValueChanged is not being called.
I think the root cause of this is PropertyGrid.Cleanup is not calling Dispose on the custom property accessors returned by our custom factory. This only happens if the tab containing the property grid is never shown - i.e. it is not the initially selected tab, and the user doesn't switch to the tab before closing the window. The factory's GetProperties method is still called even if the property grid isn't shown. I've confirmed Cleanup is definitely being called, it looks like it iterates around this.Items to dispose them, but the collection is empty.
We have a workaround for this by only adding the SelectedObject binding to the property grid when its tab is first shown.
I've sent a sample to the support address. This has two buttons that show a second window with the grid in a tab that is selected or not, then does a GC.Collect when the window is closed. There is an Assert(disposing) in the accessor's Dispose override. If the window is shown with the grid unselected and closed without selected it, the assert fires.