Abstract UserControl inheritance in Visual Studio designer

前端 未结 9 1170
广开言路
广开言路 2020-12-01 12:13
abstract class CustomControl : UserControl 
{
    protected abstract int DoStuff();
}

class DetailControl : CustomControl
{
    protected override int DoStuff()
            


        
相关标签:
9条回答
  • 2020-12-01 12:30

    Even though this question is years old, I'd like to add what I've found.

    If you don't want to touch your abstract base class, you can do this hack:

    abstract class CustomControl : UserControl 
    {
        protected abstract int DoStuff();
    }
    
    class BaseDetailControl : CustomControl
    {
        protected override int DoStuff()
        {
            throw new InvalidOperationException("This method must be overriden.");
        }
    }
    
    class DetailControl : BaseDetailControl
    {
        protected override int DoStuff()
        { 
            // do stuff
            return result;
        }
    }
    

    This way, your form inherits from a non-abstract base form and it's displayed in the designer! And you keep your abstract form, but only one more level up in the inheritance. Strange, isn't it?

    0 讨论(0)
  • 2020-12-01 12:35

    Another way to solve this is using pre-processing directives.

    #if DEBUG
      public class UserControlAdmonEntidad : UserControl, IAdmonEntidad
    #else
      public abstract class UserControlAdmonEntidad : UserControl, IAdmonEntidad
    #endif
      {
        ...
        #if DEBUG
        public virtual object DoSomething()
        {
            throw new NotImplementedException("This method must be implemented!!!");
        }
        #else
        public abstract object DoSomething();
        #endif
    
        ...
      }
    

    See this link for more information regarding this topic: Inheriting a Form from an Abstract Class (and Making it Work in the Designer)

    The same solution was also mentioned in this MSDN forum thread, in a briefer way: UserControl, Inherited Control, Abstract class, (C#)

    Maybe is not the cleaner solution, but it's still the shortest I have found.

    0 讨论(0)
  • 2020-12-01 12:39

    The following is a generic solution that works for me, mostly. It is based on the article from another answer. Sometimes it will work, and I can design my UserControl, and then later I'll open the file and it will give the "The designer must create an instance of type 'MyApp.UserControlBase' but it cannot because the type is declared as abstract." I think I can fix it by cleaning, closing VS, reopening VS, and rebuilding. Right now it seems to be behaving. Good luck.

    namespace MyApp
    {
        using System;
        using System.ComponentModel;
    
        /// <summary>
        /// Replaces a class  of <typeparamref name="T"/> with a class of
        /// <typeparamref name="TReplace"/> during design.  Useful for
        /// replacing abstract <see cref="Component"/>s with mock concrete
        /// subclasses so that designer doesn't complain about trying to instantiate
        /// abstract classes (designer does this when you try to instantiate
        /// a class that derives from the abstract <see cref="Component"/>.
        /// 
        /// To use, apply a <see cref="TypeDescriptionProviderAttribute"/> to the 
        /// class <typeparamref name="T"/>, and instantiate the attribute with
        /// <code>SwitchTypeDescriptionProvider<T, TReplace>)</code>.
        /// 
        /// E.g.:
        /// <code>
        /// [TypeDescriptionProvider(typeof(ReplaceTypeDescriptionProvider<T, TReplace>))]
        /// public abstract class T
        /// {
        ///     // abstract members, etc
        /// }
        /// 
        /// public class TReplace : T
        /// {
        ///     // Implement <typeparamref name="T"/>'s abstract members.
        /// }
        /// </code>
        /// 
        /// </summary>
        /// <typeparam name="T">
        /// The type replaced, and the type to which the 
        /// <see cref="TypeDescriptionProviderAttribute"/> must be
        /// applied
        /// </typeparam>
        /// <typeparam name="TReplace">
        /// The type that replaces <typeparamref name="T"/>.
        /// </typeparam>
        class ReplaceTypeDescriptionProvider<T, TReplace> : TypeDescriptionProvider
        {
            public ReplaceTypeDescriptionProvider() :
                base(TypeDescriptor.GetProvider(typeof(T)))
            {
                // Nada
            }
    
            public override Type GetReflectionType(Type objectType, object instance)
            {
                if (objectType == typeof(T))
                {
                    return typeof(TReplace);
                }
                return base.GetReflectionType(objectType, instance);
            }
    
            public override object CreateInstance(
                IServiceProvider provider,
                Type objectType,
                Type[] argTypes,
                object[] args)
            {
    
                if (objectType == typeof(T))
                {
                    objectType = typeof(TReplace);
                }
    
                return base.CreateInstance(provider, objectType, argTypes, args);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题