2010-11-16 10 views
7

Necesito crear un componente no visual, FooComponent, que hará algo de administración para todos los controles de tipo Bar que residen en su forma..NET (no visual) componente

que tienen las siguientes limitaciones:

  1. El FooComponent sólo se pueden añadir a los formularios.
  2. Solo se permite un FooComponent por formulario.
  3. FooComponent debe registrarse en el evento de cierre de formulario, y cuando se activa y en alguna función en todos Bar y envía el valor e.Cancel en función de los valores devueltos.

Los números 1 y 2 anteriores se deben aplicar tanto en tiempo de ejecución como en tiempo de diseño. El registro del evento # 3 debe hacerse automáticamente y no por los usuarios de FooComponent.

Busqué en Google y MSDN para obtener ayuda y leí sobre las clases Component y ComponentDesigner, pero no encontré nada para el rescate.

¿Qué debo hacer?

+0

Creo que puede ver el CodeDomSerializer (http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.codedomserializer.aspx). Puede ser tu mejor apuesta. – PHeiberg

+0

@PHeiberg: gracias –

Respuesta

3

(1) Para controlar que el componente solo se puede agregar a un formulario, use un constructor FooComponent al que se le pasa un formulario y no defina el constructor predeterminado. Se llama así:

FooComponent component = new FooComponent(this); 

donde el componente se crea desde el propio formulario. Al no definir el constructor predeterminado, esto:

FooComponent component = new FooComponent(); 

no se compilará.


(2) exponer una propiedad FooComponent en el propio formulario, y en el constructor de la FooComponent, ajuste de FooComponent a this la forma aprobada.


(3) Lo mismo, en el constructor de la FooComponent, registrarse con el acto de clausura de la forma que ha pasado


poner todo junto y se obtiene:

public class MyForm : Form { 
    public FooComponent OwnedComponent { get; set; } 
} 


public class FooComponent { 

    public FooComponent (MyForm OwnerForm) { 
     OwnerForm.OwnedComponent = this; 
     OwnerForm.FormClosing += MyCallback; 
    } 

    private void MyCallback(object sender, FormClosingEventArgs e) { 
     ... 
    } 

} 



EDIT
Lamentablemente, si necesita th El constructor predeterminado, y si tiene que ser un Componente verdadero drop-on-the-form, no hay manera de exigir que un componente solo se cree en un Formulario, o que el Formulario solo tenga una instancia del componente (no desde dentro del componente, de todos modos).

El problema es doble:
(1) Dejar caer un componente no añadir el componente a la forma, se añade a la colección de la forma components. Entonces, incluso si pudiera obtener un control para el padre/propietario, nunca será un formulario.

(2) Como señaló Neil, colocar un componente en un formulario llama al constructor predeterminado, que no pasa parámetros, y, por supuesto, ninguna de las propiedades del componente (como sitio o contenedor) se rellena.


Posiblemente útil: Un componente puede ser diseñado para ser notificado cuando se crea en un par de maneras:

(1) Mediante la implementación de un constructor que toma un parámetro IContainer. Cuando el componente se descarta en un formulario, el código generado llamará a este constructor, en su lugar. Sin embargo, solo hará esto en tiempo de ejecución, no en tiempo de diseño. Pero el contenedor será un identificador de la colección components del formulario.

public FooComponent(IContainer container) {...} 

(2) Implementando ISupportInitialize. Cuando el componente se descarta en un formulario, el código generado también llamará al BeginInit() y al EndInit(). En EndInit(), puede acceder a propiedades como Site y Container. Nuevamente, solo obtendrá esto en tiempo de ejecución, no en tiempo designado, y lanzar una excepción aquí no impedirá que se cree el componente.

Artículos antiguos, pero excelentes sobre componentes y controles de MSDN Magazine de Michael Weinhardt y Chris Sells.
April 2003 Building Windows Forms Controls and Components with Rich Design-Time Features
May 2003 Building Windows Forms Controls and Components with Rich Design-Time Features, Part 2

Estos son ahora los archivos de ayuda .chm. Deberá desbloquear en la página de propiedades del archivo para permitir la lectura de los contenidos después de la descarga.

+0

La desventaja de no permitir un constructor vacío es que no podrá usar el control en tiempo de diseño. –

+0

El OP dice que es un componente no visual que está creando, por lo que esto no debería ser un problema. El constructor que quiero decir es el constructor de FooComponent ... Voy a aclarar que en la pregunta –

+0

veo lo que quieres decir ... si literalmente significa un 'Componente' que quiere arrastrar y soltar en el formulario, entonces estás bien, él tiene que tener un constructor predeterminado. –

1

No creo que sea posible definir exactamente qué clase contenida puede contenerse. Ciertamente, nunca he visto una instancia en la que obtuve un error (o incluso una advertencia) para configurar una propiedad de un tipo en otro, incluso en WinForms.

Algo que podría hacer es definir un antecesor derivado de formulario para sus formularios que contenga una referencia a su FooComponent (visible internamente), inicialice uno en la creación de instancias y una los manejadores. Para obtener los mejores resultados, debe ser sin parámetros y la única sobrecarga del constructor, por lo que constituye la base para cualquier constructor que sus consumidores generen. Luego, simplemente convierta en regla de la casa que las formas se derivan de su clase antecesora y no directamente de Formulario (es posible que pueda usar una herramienta de inspección de código como FxCop o similar para aplicar esto cuando el código está comprometido con el control de fuente). Sus usuarios ahora obtienen un FooComponent en cada Formulario que crean, no pueden crear el suyo (es interno y debe estar en otro proyecto con su Ancestro del Formulario) y no tienen que hacer nada más que derivar de la nueva clase para hacer que sus formularios se comporten la forma que tu quieras.

+0

Necesito esto para ser compatible con el tiempo de diseño, ¿sabe de todos modos para alcanzar el # 3 en tiempo de diseño? –

1

Usted está pidiendo mucho. En general, hacer que los componentes tomen conciencia de la forma en que se dejan caer es bastante difícil. This answer puede ayudarlo a implementar el controlador de eventos. Deberá implementar ISupportInitialize para obtener la llamada EndInit() para configurar el controlador de eventos.

La prevención de los múltiplos también es bastante difícil, solo puedo pensar en un diseñador personalizado que pueda intervenir lo suficientemente temprano para evitar que se agregue el segundo.

Cuestiones relacionadas