C# Visual Studio designer中的抽象用户控件继承

C# Visual Studio designer中的抽象用户控件继承,c#,winforms,abstract-class,user-controls,C#,Winforms,Abstract Class,User Controls,我在表单中删除了一个DetailControl。它在运行时正确呈现,但设计器显示错误并且不会打开,因为基本用户控件是抽象的 目前,我正在考虑下面的补丁,这对我来说似乎非常错误,因为我希望强制子类实现该方法 abstract class CustomControl : UserControl { protected abstract int DoStuff(); } class DetailControl : CustomControl { protected override

我在表单中删除了一个DetailControl。它在运行时正确呈现,但设计器显示错误并且不会打开,因为基本用户控件是抽象的

目前,我正在考虑下面的补丁,这对我来说似乎非常错误,因为我希望强制子类实现该方法

abstract class CustomControl : UserControl 
{
    protected abstract int DoStuff();
}

class DetailControl : CustomControl
{
    protected override int DoStuff()
    { 
        // do stuff
        return result;
    }
}

有人对如何解决这个问题有更好的想法吗?

您可以使用TypeDescriptionProviderAttribute为抽象基类提供具体的设计时实现。有关详细信息,请参阅。

解决此问题的另一种方法是使用预处理指令

class CustomControl : UserControl 
{
    protected virtual int DoStuff()
    {
        throw new InvalidOperationException("This method must be overriden.");
    }
}

class DetailControl : CustomControl
{
    protected override int DoStuff()
    { 
        // do stuff
        return result;
    }
}
有关此主题的更多信息,请参阅此链接:

同样的解决方案也在本MSDN论坛帖子中以更简单的方式提及:


也许不是更干净的解决方案,但它仍然是我找到的最短的解决方案。

以下是一个基本上适用于我的通用解决方案。这是基于另一个答案的结论。有时它会工作,我可以设计我的
UserControl
,然后我打开文件,它会给出“设计器必须创建一个'MyApp.UserControlBase'类型的实例,但它不能,因为该类型声明为抽象。”我想我可以通过清理、关闭VS、重新打开VS和重建来修复它。现在,它似乎正在行动。祝你好运

#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

    ...
  }
名称空间MyApp
{
使用制度;
使用系统组件模型;
/// 
///将的类替换为的类
///在设计期间。对于
///用模拟混凝土代替抽象混凝土
///子类,这样设计器就不会抱怨试图实例化
///抽象类(当您尝试实例化时,设计器会执行此操作
///从抽象派生的类。
/// 
///若要使用,请将
///类,并使用
///
SwitchTypeDescriptionProvider)
。 /// ///例如: ///

///[TypeDescriptionProvider(typeof(ReplaceTypeScriptionProvider))]
///公共抽象类T
/// {
/////抽象成员等
/// }
/// 
///公共课地点:T
/// {
/////实现的抽象成员。
/// }
///
/// /// /// ///替换的类型,以及 ///一定是 ///应用 /// /// ///替换的类型。 /// 类替换TypeDescriptionProvider:TypeDescriptionProvider { public ReplaceTypeDescriptionProvider(): base(TypeDescriptor.GetProvider(typeof(T))) { //娜达 } 公共重写类型GetReflectionType(类型objectType,对象实例) { if(objectType==typeof(T)) { 返回类型(TReplace); } 返回base.GetReflectionType(objectType,instance); } 公共重写对象实例( IServiceProvider提供程序, 类型objectType, 类型[]argTypes, 对象[]args) { if(objectType==typeof(T)) { objectType=typeof(TReplace); } 返回base.CreateInstance(提供程序、objectType、argTypes、args); } } }
我只是将抽象基类定义为一个具体的基类,将“抽象”方法定义为虚拟方法,并在其中抛出一个异常,以防任何顽皮的派生类试图调用基类实现

e、 g

这与实际抽象基类之间的主要实际区别在于,调用基类实现时会出现运行时错误,而如果基类实际上是抽象的,编译器将不允许意外调用基类实现。这对我来说没什么大不了的,并且允许我使用设计器,而不用担心其他人建议的更复杂、更耗时的解决方案


PS-Akuma-您应该能够在设计器中编辑抽象UI类。我现在没有时间检查这一点,但我的理解是,设计器只需要实例化基类。只要您设计的类的基础是具体的,那么设计的类是什么并不重要。

我们想要什么

首先,让我们定义最终类和基本抽象类

    class Base : UserControl
    {
        protected virtual void BlowUp()
        {
            throw new NotSupportedException("This method MUST be overriden by ALL derived classes.");
        }

    class Derived : Base
    {
        protected override void BlowUp()
        {
            // Do stuff, but don't call base implementation,
            // just like you wouldn't (can't actually) if the Base was really abstract. 
            // BTW - doesn't blow up any more  ;)
        }
现在我们只需要一个描述提供程序

public class MyControl : AbstractControl
...
public abstract class AbstractControl : UserControl // Also works for Form
...
就这样。不需要中间控制


在同一个解决方案中,provider类可以应用于任意多个抽象基。

即使这个问题已经存在多年了,我还是想补充一下我的发现

如果不想接触抽象基类,可以进行以下操作:


这样,您的表单继承自非抽象基表单,并显示在设计器中!您保留了抽象形式,但只在继承中再上一层。很奇怪,不是吗?

我不能用工作来解决“妮可·卡里诺”的问题。但直接在VisualStudio中还有一种简单的方法:)

  • 创建新项目
  • 例如,添加新元素“userControl”并添加一个按钮
  • 添加新元素“userControl”Inhered userControl,然后选择Inhered userControl

  • 这里有更多详细信息:“

    我在自定义控件的UWP中解决了这个问题

    我的案例

    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;
        }
    }
    
    声明

    public abstract class BaseModel : DependencyObject 
    
    {
    ...
    }
    
    public class MainModel : BaseModel
    
    {
    
    public bool ShowLabel
    
    {
        get{ return (bool)GetValue(ShowLabelProperty); }
        set{ SetValue(ShowLabelProperty, value) }
    }
    
    public static readonly DependencyProperty ShowLabelProperty =
    
        DependencyProperty.Register("ShowLabel",typeof(bool), typeof(MainModel), new PropertyMetadata(false));
    
    }
    
    
    
    解决方案

    public abstract class BaseModel : DependencyObject 
    
    {
    ...
    }
    
    public class MainModel : BaseModel
    
    {
    
    public bool ShowLabel
    
    {
        get{ return (bool)GetValue(ShowLabelProperty); }
        set{ SetValue(ShowLabelProperty, value) }
    }
    
    public static readonly DependencyProperty ShowLabelProperty =
    
        DependencyProperty.Register("ShowLabel",typeof(bool), typeof(MainModel), new PropertyMetadata(false));
    
    }
    
    只需覆盖泛型资源中的虚拟样式

    < MyCustomControl:MainModel ShowLabel=True />
    
    
    
    问候,


    塞缪尔(Samuel)

    我是UWP的新手,这让我发疯。我没有想到UserControl的抽象基类。我走了另一个方向。我创建了一个非xaml助手类<代码>HBase。每个视图,比如说
    VContract
    ,都有相应的
    public abstract class BaseModel : DependencyObject 
    
    {
    ...
    }
    
    public class MainModel : BaseModel
    
    {
    
    public bool ShowLabel
    
    {
        get{ return (bool)GetValue(ShowLabelProperty); }
        set{ SetValue(ShowLabelProperty, value) }
    }
    
    public static readonly DependencyProperty ShowLabelProperty =
    
        DependencyProperty.Register("ShowLabel",typeof(bool), typeof(MainModel), new PropertyMetadata(false));
    
    }
    
    < MyCustomControl:MainModel ShowLabel=True />
    
    <Style TargetType="local:MainModel" />
    
    if (false == Windows.ApplicationModel.DesignMode.DesignModeEnabled)
    {
                HContract = new HContract(this);
    //   Put code here that fails in Design mode but must at run time               
    }