Yesterday the need arised for inheriting a WinForms user control to implement four specializations of a user control. Creating inherited user controls is very simple in Visual Studio, just click 'Add-New item' and select 'Inherited user control', name the new user control appropiately and click 'Add'. I then selected the user control to derive from (note that the class must be plain public, while the constructor can be protected) and clicked OK.
VS2005 dutifully added the new user control files, but the VS designer failed with this error message:
One or more errors encountered while loading the designer. The errors are listed below. Some errors can be fixed by rebuilding your project, while others may require code changes.
Object reference not set to an instance of an object.
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
. . .
at Microsoft.VisualStudio.Design.Serialization.CodeDom. VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio. TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
Some googling did provided me with only a few similar problems, but none of the suggested solutions worked for me. Even adding two new user controls with no code or children would fail when trying to inherit one from the other.
The designer always calls the user control's parameterless constructor New and the control's Load event handler (provided that they exists), thus these methods should not do any operations that depend on some run-time resources.
I was quite puzzled when even added the two new plain user controls failed, as they of course had no constructor or load event handler. Then I noted that I could no longer open any user controls or forms in the whole solution. The VS designer had gone into a zombie state. A restart of Visual Studio, plus clearing the TFS workspace cache, corrected the VS designer problem for all the forms and the non-inherited user controls. Before I even tried to add a derived user control again, I did the recommended rebuild (see error message above) to ensure that coding errors did not cause the problem.
This time I added a standard user control and manually added the Inherits statement to the class code file and the designer partial class file. Then I opened the user control in designer mode, and I still got the famous designer error page, but this time with useful error details pointing me to a specific line in the base class.
The offending line was a private class member that created a biz-logic component using the abstract factory pattern:
Public Class GenericUCBase
. . .
Private _bizManager As IBizManager = ObjectFactory.BizManager()
. . .
Protected Sub New()
' This call is required by the Windows Form Designer.
. . .
The factory uses a Public Shared (static) method that creates objects using the dependency injection pattern (interface based) from pre-compiled assemblies deployed to the VS project location. It was the Type.GetType(typeName as String) method that failed when called from the private member initialization. I don't know why the VS designer failed to locate my assemblies during initialization, VS has no problems with non-derived controls, or with running or debugging the project.
All class members that are "declare initialized" gets called when the designer loads a user control, along with the constructor and the load event handler. Knowing this, I moved the initialization of the biz-logic component to my InitControl method, and this solved the VS designer problem.
The TFS workspace cache is located here:
\Documents and Settings\%user%\Local Settings\Application Data\Microsoft\Team Foundation\1.0\Cache
I clear it whenever I have problems with VS or TFVC, typically when the 'pending check-ins' list contains bogus entries from other solutions that cannot be removed in any other way.