I got sick of Notepad a couple weeks ago, and set about to build a Notepad-like application with a couple sorely missing features like reload prompting, multiple undo levels, tabs, line numbers, more robust find and replace, recent files list, opacity, etc. It's a cool little project, titled DevNotepad, and is currently about 3,000 lines of code. It's fast too, which is very important for a Notepad replacement. The beauty of Notepad itself is its compact size and loading speed. More on DevNotepad later.
Along the way though, I ran into a problem trying to visually design user controls which inherited from an abstract class. Out of the install (box), Visual Studio does not support this. If you were to try and visually design a form which inherits from an abstract class, you would get a message similar to the following:
After digging through [your favorite search engine], I found it is possible to modify this behavior. The key is to provide a TypeDescriptionProvider attribute to the base abstract class:
[TypeDescriptionProvider(typeof(SubstituteBaseUserControlProvider))]
public abstract class BaseUserControl : UserControl
...
If you don't have Reflector installed, TypeDescriptorProvider is in the System.ComponentModel namespace. The next step is to build the actual provider itself:
internal class ReplaceOptionsPageProvider : TypeDescriptionProvider
{
public ReplaceOptionsPageProvider()
: base(TypeDescriptor.GetProvider(typeof(BaseOptionsPage)))
{
}
public override Type GetReflectionType(Type objectType, object instance)
{
if (objectType == typeof (BaseOptionsPage))
return typeof (ReplaceForm);
return base.GetReflectionType(objectType, instance);
}
public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
{
if (objectType == typeof (BaseOptionsPage))
objectType = typeof (ReplaceForm);
return base.CreateInstance(provider, objectType, argTypes, args);
}
}
The above code detects if the user control to be designed inherits from the aforementioned abstract class, and gives it a replacement to start designing from – a stand-in base class. Therefore, the final step is to build the stand-in user control, inheriting from the original abstract class:
internal class StandInUserControl : BaseOptionsPage
Once the code is in place, close any open designer windows, rebuild the project, and re-open the previously troublesome designer. You should be good to go.
Hope this helps