2011-06-09 9 views
6

Quiero tener un resumen UserControl, BaseControl, que implementa una interfaz IBaseControl. Sin embargo, el establecimiento de la clase de abstraer diseñador rompe VisualStudio (Esto es un problema conocido con Visual Studio (por ejemplo, véase this StackOverflow posting para más información), y por lo que yo sé, no hay no change expected in the near futureVisualStudio 2010 Designer lanza en el método virtual implementado

lo tanto, para evitar esto, . hago BaseControl no es abstracto, y su puesta en práctica de IBaseControl métodos virtuales sin embargo, puesto que estos métodos no tienen sentido para un BaseControl (por ejemplo, no todos los componentes se han añadido aún), hago que tiran:

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(); 
    } 
} 

En el control derivado, tengo la anulación correspondiente:

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

A pesar de esto, cuando intento abrir el control en el diseñador, aparece un error que indica que BaseControl.LoadSettings ha lanzado una excepción.

Ahora, recuerde que LoadSettings se llama en la clase base, por lo que cuando el Diseñador carga el DerivedControl, a su vez llama al método de carga para el BaseControl, que arroja.

¿Ha encontrado un problema similar? ¿Cómo has lidiado con esto? Me gustaría tener una solución elegante, si es posible.

+0

Sin repro, no esperaba uno. Ahora tiene dos controles en la barra de herramientas, no elija el incorrecto. Realmente debería anular OnLoad en lugar de usar el evento Load. –

Respuesta

6

La razón por la que se lanza la excepción es porque, por extraño que parezca, el diseñador no compila ni ejemplifica la clase que está diseñando en absoluto! Solo compila e instaura la clase base del control que está diseñando.

Por qué este es el caso se vuelve obvio cuando se da cuenta de que agregar nuevos subcontroles al elemento requeriría una recompilación adicional. Además, cada controlador de eventos que agregue modifica la clase y de nuevo requerirá recompilación. Como los controladores de eventos nunca serán llamados en el diseñador de todos modos, esto es completamente innecesario. Usted diseña con una clase que se asemeja a su clase pero no es su clase; Es un trabajo en progreso.

Dado que solo se crea una instancia de la clase base, la clase base no puede ser abstracta y debe ser funcional como es. Si arrojas excepciones, el diseñador las verá. La única solución práctica es ya sea:

  • No lanzar excepciones de la clase base, o
  • condicionalmente no lanza excepciones en función de si es tiempo de diseño o no.

Cualquiera de los dos funcionará; utilice el que prefiera o que funcione mejor para su diseño. Así es como funciona el diseñador y, como usted menciona, no es probable que cambie.

+1

¡Impresionante, esto es! Ahora estoy usando 'if (! DesignMode)' para lanzar condicionalmente. –

Cuestiones relacionadas