visuales tag propiedades personalizados para los formularios elaborar controles componentes .net winforms user-controls design-time windows-forms-designer

.net - tag - Líneas de referencia básicas en controles personalizados de Winforms



propiedades de windows forms en c# (5)

Tengo un control de usuario personalizado con un cuadro de texto y me gustaría exponer la línea de referencia (del texto en el cuadro de texto) fuera del control personalizado. Sé que crea un diseñador (heredado de ControlDesigner) y anula SnapLines para tener acceso a los snapines, pero me pregunto cómo obtener la línea de base de texto de un control que he expuesto por mi control de usuario personalizado.


Como una actualización de la respuesta de Miral ... aquí hay algunos de los "pasos que faltan", para alguien nuevo que está buscando cómo hacer esto. :) El código de C # de arriba está casi listo para usar, con la excepción de cambiar algunos de los valores para hacer referencia al UserControl que se modificará.

Posibles referencias necesarias:
System.Design (@robyaw)

Usos necesarios:

using System.Windows.Forms.Design; using System.Windows.Forms.Design.Behavior; using System.ComponentModel; using System.ComponentModel.Design; using System.Collections;

En su UserControl necesita el siguiente atributo:

[Designer(typeof(MyCustomDesigner))]

Entonces necesitas una clase de "diseñador" que tendrá la anulación de SnapLines:

private class MyCustomerDesigner : ControlDesigner { public override IList SnapLines { get { /* Code from above */ IList snapLines = base.SnapLines; // *** This will need to be modified to match your user control MyControl control = Control as MyControl; if (control == null) { return snapLines; } // *** This will need to be modified to match the item in your user control // This is the control in your UC that you want SnapLines for the entire UC IDesigner designer = TypeDescriptor.CreateDesigner( control.textBoxValue, typeof(IDesigner)); if (designer == null) { return snapLines; } // *** This will need to be modified to match the item in your user control designer.Initialize(control.textBoxValue); using (designer) { ControlDesigner boxDesigner = designer as ControlDesigner; if (boxDesigner == null) { return snapLines; } foreach (SnapLine line in boxDesigner.SnapLines) { if (line.SnapLineType == SnapLineType.Baseline) { // *** This will need to be modified to match the item in your user control snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + control.textBoxValue.Top, line.Filter, line.Priority)); break; } } } return snapLines; } } } }


Estás en el camino correcto. Tendrá que anular la propiedad SnapLines en su diseñador y hacer algo como esto:

Public Overrides ReadOnly Property SnapLines() As System.Collections.IList Get Dim snapLinesList As ArrayList = TryCast(MyBase.SnapLines, ArrayList) Dim offset As Integer Dim ctrl As MyControl = TryCast(Me.Control, MyControl) If ctrl IsNot Nothing AndAlso ctrl.TextBox1 IsNot Nothing Then offset = ctrl.TextBox1.Bottom - 5 End If snapLinesList.Add(New SnapLine(SnapLineType.Baseline, offset, SnapLinePriority.Medium)) Return snapLinesList End Get End Property

En este ejemplo, usercontrol contiene un cuadro de texto. El código agrega una nueva línea de inserción que representa la línea de base para el cuadro de texto. Lo importante es calcular el desplazamiento correctamente.


Gracias a todos por la ayuda. Esto fue difícil de tragar. La idea de tener una subclase privada en cada UserControl no era muy aceptable.

Vine con esta clase base para ayudar ...

[Designer(typeof(UserControlSnapLineDesigner))] public class UserControlBase : UserControl { protected virtual Control SnapLineControl { get { return null; } } private class UserControlSnapLineDesigner : ControlDesigner { public override IList SnapLines { get { IList snapLines = base.SnapLines; Control targetControl = (this.Control as UserControlBase).SnapLineControl; if (targetControl == null) return snapLines; using (ControlDesigner controlDesigner = TypeDescriptor.CreateDesigner(targetControl, typeof(IDesigner)) as ControlDesigner) { if (controlDesigner == null) return snapLines; controlDesigner.Initialize(targetControl); foreach (SnapLine line in controlDesigner.SnapLines) { if (line.SnapLineType == SnapLineType.Baseline) { snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + targetControl.Top, line.Filter, line.Priority)); break; } } } return snapLines; } } } }

A continuación, obtenga su UserControl desde esta base:

public partial class MyControl : UserControlBase { protected override Control SnapLineControl { get { return txtTextBox; } } ... }

Gracias de nuevo por publicar esto.


Simplemente tenía una necesidad similar, y lo resolví así:

public override IList SnapLines { get { IList snapLines = base.SnapLines; MyControl control = Control as MyControl; if (control == null) { return snapLines; } IDesigner designer = TypeDescriptor.CreateDesigner( control.textBoxValue, typeof(IDesigner)); if (designer == null) { return snapLines; } designer.Initialize(control.textBoxValue); using (designer) { ControlDesigner boxDesigner = designer as ControlDesigner; if (boxDesigner == null) { return snapLines; } foreach (SnapLine line in boxDesigner.SnapLines) { if (line.SnapLineType == SnapLineType.Baseline) { snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + control.textBoxValue.Top, line.Filter, line.Priority)); break; } } } return snapLines; } }

De esta manera, en realidad está creando un sub-diseñador temporal para el subcontrol con el fin de averiguar dónde se encuentra la línea de referencia "real".

Esto pareció razonablemente efectivo en las pruebas, pero si perf se convierte en una preocupación (y si el cuadro de texto interno no se mueve), la mayoría de este código se puede extraer al método Initialize.

Esto también asume que el cuadro de texto es un hijo directo del UserControl. Si hay otros controles que afectan el diseño en el camino, entonces el cálculo del desplazamiento se vuelve un poco más complicado.


Versión de VB.Net:
Nota: debe cambiar el txtDescription al txtDescription de texto u otro nombre de control interno que use. y ctlUserControl a su nombre de ctlUserControl de ctlUserControl

<Designer(GetType(ctlUserControl.MyCustomDesigner))> _ Partial Public Class ctlUserControl ''... ''Your Usercontrol class specific code ''... Class MyCustomDesigner Inherits ControlDesigner Public Overloads Overrides ReadOnly Property SnapLines() As IList Get '' Code from above Dim lines As IList = MyBase.SnapLines '' *** This will need to be modified to match your user control Dim control__1 As ctlUserControl = TryCast(Me.Control, ctlUserControl) If control__1 Is Nothing Then Return lines '' *** This will need to be modified to match the item in your user control '' This is the control in your UC that you want SnapLines for the entire UC Dim designer As IDesigner = TypeDescriptor.CreateDesigner(control__1.txtDescription, GetType(IDesigner)) If designer Is Nothing Then Return lines End If '' *** This will need to be modified to match the item in your user control designer.Initialize(control__1.txtDescription) Using designer Dim boxDesigner As ControlDesigner = TryCast(designer, ControlDesigner) If boxDesigner Is Nothing Then Return lines End If For Each line As SnapLine In boxDesigner.SnapLines If line.SnapLineType = SnapLineType.Baseline Then '' *** This will need to be modified to match the item in your user control lines.Add(New SnapLine(SnapLineType.Baseline, line.Offset + control__1.txtDescription.Top, line.Filter, line.Priority)) Exit For End If Next End Using Return lines End Get End Property End Class End Class