2011-06-09 47 views
6

我想要一个摘要UserControl,BaseControl,它实现了一个接口IBaseControl。 然而,设置类抽象休息VisualStudio的设计(这是与Visual Studio(例如,参见this StackOverflow posting获取更多信息),而据我所知,有no change expected in the near futureVisualStudio 2010 Designer引发实现的虚拟方法

于是,一个已知的问题来解决这个问题,我让BaseControl不是抽象的,其实现的IBaseControl方法虚拟然而,由于这些方法并没有什么意义了BaseControl(例如,不是所有组件都已经被添加),我让他们扔:

public class BaseControl : UserControl, IBaseControl 
{ 
    /// <summary> 
    /// This IBaseControl method is not abstract because 
    /// that breaks the Designer 
    /// </summary> 
    public virtual void LoadSettings() 
    { 
     throw new NotImplementedException("Implement in derived class."); 
    } 

    private void BaseControl_Load(object sender, EventArgs e) 
    { 
     // intention: derived methods automagically load their settings 
     this.LoadSettings(); 
    } 
} 

在导出的控件,我有相应的覆盖:

public partial class DerivedControl : BaseControl 
{ 
    public override void LoadSettings() 
    { 
     // load settings 
    } 
} 

尽管如此,当我尝试在设计器中打开控件时,出现一个错误,指示BaseControl.LoadSettings引发了异常。

现在,请记住LoadSettings是在基类中调用的,所以当Designer加载DerivedControl时,它依次调用BaseControl的加载方法,该方法会抛出。

您是否遇到过类似问题?你怎么处理这件事?如果可能的话,我想有一个优雅的解决方案。

+0

没有repro,我没有想到一个。现在工具栏上有两个控件,不要选错了。你应该重写OnLoad而不是使用Load事件。 – 2011-06-09 20:53:54

回答

6

引发异常的原因是,奇怪的是,设计师并没有编译或实例化您正在设计的类!它只编译和实例化正在设计的控件的基类。

为什么这种情况变得很明显,当你意识到为元素添加新的子控件需要进一步的重新编译。此外,您添加的每个事件处理程序都会修改该类,并再次需要重新编译。由于事件处理程序永远不会在设计器中调用,所以这完全没有必要。你设计一个类类似你的班,但不是你的班;这是一项正在进行中的工作。

因为只有基类被实例化,所以基类不能抽象,它需要功能,就像一样。如果你抛出异常,那么设计者就会看到它们。唯一可行的解​​决方案是:

  • 不从基类抛出异常,或
  • 有条件地不扔基于它是否是设计时还是不例外。

要么会工作;使用你喜欢的或最适合你的设计的。这只是设计师的工作方式,因为你提到它不太可能改变。

+1

太棒了,就是这样!我现在使用'if(!DesignMode)'有条件地抛出。 – 2011-06-09 20:57:13