¿Cómo establecería la etiqueta de mi UserControl en tiempo de diseño?

Aquí está la configuración: he creado un control de usuario MyUserControl. En este control hay una etiqueta simple. Cuando coloco una nueva instancia de este control en un formulario, me gustaría que la etiqueta fuera el nombre del control. Por ejemplo, si esta es la primera instancia del control, VStudio establece automáticamente el nombre del mismo en "myUserControl1". Simplemente me gustaría que la etiqueta dijera "myUserControl1". Si este es el quinto control, VStudio lo llamará myUserControl5. Me gustaría que la etiqueta cambiara en consecuencia ... pero solo si aún no se ha configurado. Una vez que lo configuro para que lea "La etiqueta", debe dejarse solo.

Pensé que iba a ser fácil. En el constructor, establezca label1.Text = this.Name. Pero luego me di cuenta, en la instanciación de this.Name es simplemente MyUserControl. VisualStudio y el método CONTAINING InitializeComponent () aún no lo han nombrado.

¡Ah! Simplemente anularé el campo "Nombre". ¡Cuando se configure, verifique DesignMode y actualice la etiqueta! ... pero no puedo anular el nombre. No es virtual ni abstracto. Puedo usar "nuevo" para forzarlo, pero luego, nunca se dispara, frustrando así el propósito.

¿Qué evento puedo usar para indicar cuándo el diseñador ha nombrado el control? Sé que la gente de Redmond lo hace todo el tiempo cuando sueltan un control en el formulario, así que es muy posible. De hecho, estoy bastante perplejo con este pequeño acertijo.

preguntado el 08 de noviembre de 11 a las 15:11

Reto interesante. Solo se me ocurrieron algunas formas que funcionan bien hasta que elimine o corte / pegue cualquiera de los controles de usuario. La propiedad Name simplemente no parece haber cambiado en el momento del diseño. Tengo que hacer un trabajo de verdad ahora ... ¡buena suerte! -

Esto requiere un diseñador personalizado. ControlDesigner.InitializeNewComponent () es un buen ejemplo. El problema es que el diseñador de UserControl no es público, por lo que no se puede derivar de. -

3 Respuestas

¿Qué hay de anular el OnLoad método, que llama al Carga ¿evento?

Si eso no funciona, es un poco descuidado, pero podrías usar el TextChanged evento, o el SizeChanged evento ya que ambos se llaman después de la Name La propiedad la establece el diseñador (establece los valores en orden alfabético).

respondido 08 nov., 11:19

Todavía dejó el nombre como "MyUserControl" en lugar de myUserControl5. - alemán

¿Ambos? Hmmm ... mi única otra sugerencia sería configurar un temporizador para esperar, seguir verificando un cambio (y luego detenerlo cuando haya un cambio). - Connell

No. Estoy seguro de que el evento TextChanged o SizeChanged funcionaría, pero, como notó, es muy descuidado. Sé que tiene que haber un método muy simple para hacer esto. La introducción de un código descuidado para algo tan simple seguramente conducirá a otros errores en el futuro. - alemán

Esto es muy cierto y estaría buscando otra manera si estuviera en tus zapatos. Pero si llegara a eso y no pudiera encontrar una mejor manera, lo implementaría y lo comentaría fuertemente explicando lo que hace para referencia futura ... Connell

¿Quizás deberías reconsiderar el razonamiento? Quizás el nombre no sea lo correcto para el trabajo. Por lo general, el diseñador establece la propiedad Text de un UserControl a este nombre, ¿podrías usarlo? - Connell

Entonces, aquí está la respuesta final:

Según la sugerencia de Hans, requería un ControlDesigner. Creé un diseñador simple que interactuaría con algunas propiedades internas, y lo hice funcionar. Sin embargo, aquí está el truco: es un truco. No parece haber un solo campo que tenga el valor que estoy buscando, así que tuve que hacer un .ToString() en un objeto, luego analice la primera sección. Supuse que eso es lo más limpio posible.

public class MyControlDesigner : ControlDesigner
{
    public MyControlDesigner()
    {
    }


    public override void InitializeNewComponent(IDictionary defaultValues)
    {
        base.InitializeNewComponent(defaultValues);

        MyControl control1 = this.Component as MyControl;
        control1.LabelText = control1.ToString().Split(" ".ToCharArray())[0];
    }
}

Luego, en la parte superior de MyControl, simplemente agregué un nuevo atributo:

[DesignerAttribute(typeof(MyControlDesigner))]
public partial class MyControl : UserControl
{
    ...

    // Using the property "Text" Causes Visual Studio to crash!!!
    public string LabelText
    {
        get { return label1.Text; }
        set { label1.Text = value; }
    }

    ...
}

Como puede ver, no fue muy complicado, pero es un poco pirateado. El control bloqueó el IDE cuando intenté anular "Texto". No estoy seguro de por qué, pero cuando lo llamé "LabelText", funcionó perfectamente.

respondido 11 nov., 11:23

UserControl ya tiene una propiedad de texto, por lo que debe cambiarla a "texto de cadena nueva pública {..." para poder usarlo. - LarsTech

Edite el archivo del diseñador. Por ejemplo, digamos que tengo un formulario llamado Form1. Entonces, tendría Form1.cs, Form1.resx y Form1.Designer.cs en Visual Studio. Si abre Form1.Designer.cs, verá esto:

   #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>

Esta es una advertencia, pero aún puede editar este archivo.

Aquí hay una edición de muestra, estoy configurando el texto de label3 en el nombre de label1:

            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(371, 146);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(35, 13);
            this.label3.TabIndex = 10;
            this.label3.Text = "label3";
            //My Edit
            this.label3.Text = this.label1.Name;

Ahora, en el diseñador de formularios de Visual Studio, veo que label3 tiene el nombre de label1:

enter image description here

Se podría utilizar un enfoque similar para su control de usuario.

respondido 08 nov., 11:23

El diseñador puede volver a generar este código en cualquier momento y lo volverá a poner en una cadena constante cada vez que se actualice. Además, en este momento no puede garantizar que label1.Name ha sido establecido. - Connell

Buen punto, definitivamente tendría que hacer un comentario o alertar a todos de esto porque el cambio podría desaparecer inadvertidamente. Cualquier código autogenerado tiene este problema, de ahí la advertencia en la parte superior del archivo de código. Siempre que el código personalizado sea posterior a la configuración de label1.name, está bien. Sería necesario mirar el código del diseñador para asegurarse de que el código cutom esté en el lugar correcto. No digo que esto sea lo mejor, pero podría ser una solución viable. No creo que haya acceso directo al archivo del diseñador generado automáticamente más allá de la edición de la plantilla. - Jon Raynor

En efecto. Sin embargo, ninguna solución es perfecta. Por lo general, si no hay una manera fácil de hacerlo, significa que Microsoft no quiere que lo haga. Sin embargo, no puedo ver su razonamiento para este. - Connell

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.