c# - winform - Control de usuario como contenedor en tiempo de diseño
xaf devexpress documentation (3)
Además de la respuesta anterior. Se menciona en los comentarios, que el usuario puede arrastrar el área de trabajo. Mi solución para eso es incluir el panel WorkingArea en otro panel, configurándolo en Dock.Fill. Para no permitir que el usuario vuelva a cambiarlo, he creado un ContentPanel de clase que reemplaza y oculta la propiedad Dock:
class ContentPanel : Panel
{
[Browsable(false)]
public override DockStyle Dock
{
get { return base.Dock; }
set { base.Dock = DockStyle.Fill; }
}
}
Para mí, esto lo hace suficientemente seguro. Solo estamos usando el control internamente, por lo que principalmente queremos evitar que los desarrolladores arrastren las cosas accidentalmente. Ciertamente hay maneras de desordenar de todos modos.
Estoy diseñando un simple control de expansión.
Derivé de UserControl, dibujé controles internos, construí, ejecuté; todo bien.
Dado que un Control interno es un Panel, me gustaría usarlo como contenedor en el momento del diseño. De hecho he usado los atributos:
[Designer(typeof(ExpanderControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
Genial lo digo Pero no es ...
El resultado es que puedo usarlo como contenedor en el momento del diseño pero:
- Los controles agregados vuelven a los controles internos ya integrados en el control del usuario.
- Incluso si presiono para superar un control agregado en el momento del diseño, en el tiempo de ejecución vuelve a estar en los controles integrados al control del usuario
- No puedo restringir el área del contenedor en el momento del diseño en un área del Panel
¿Qué me estoy perdiendo? Aquí está el código para completar ... ¿por qué este fragmento de código no funciona?
[Designer(typeof(ExpanderControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ExpanderControl : UserControl
{
public ExpanderControl()
{
InitializeComponent();
....
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class ExpanderControlDesigner : ControlDesigner
{
private ExpanderControl MyControl;
public override void Initialize(IComponent component)
{
base.Initialize(component);
MyControl = (ExpanderControl)component;
// Hook up events
ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService));
IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService));
s.SelectionChanged += new EventHandler(OnSelectionChanged);
c.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving);
}
private void OnSelectionChanged(object sender, System.EventArgs e)
{
}
private void OnComponentRemoving(object sender, ComponentEventArgs e)
{
}
protected override void Dispose(bool disposing)
{
ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService));
IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService));
// Unhook events
s.SelectionChanged -= new EventHandler(OnSelectionChanged);
c.ComponentRemoving -= new ComponentEventHandler(OnComponentRemoving);
base.Dispose(disposing);
}
public override System.ComponentModel.Design.DesignerVerbCollection Verbs
{
get
{
DesignerVerbCollection v = new DesignerVerbCollection();
v.Add(new DesignerVerb("&asd", new EventHandler(null)));
return v;
}
}
}
He encontrado muchos recursos ( Interaction , área limitada , designed ), pero nada fue útil para ser operativo ...
En realidad, hay un truco, ya que las clases System.Windows.Forms pueden diseñarse (como es habitual) y tener un comportamiento correcto en tiempo de ejecución (TabControl, por ejemplo).
Para evitar que el área de trabajo se mueva / cambie de tamaño en el diseñador, debe crear una clase para esa área de trabajo que oculta las propiedades de Ubicación, Altura, Ancho, Tamaño del diseñador:
public class WorkingArea : Panel
{
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
}
}
...
}
ParentControlDesigner no sabe lo que quieres hacer. Solo sabe que desea que su UserControl sea un contenedor.
Lo que debe hacer es implementar su propio diseñador que habilite el modo de diseño en el panel:
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace MyCtrlLib
{
// specify my custom designer
[Designer(typeof(MyCtrlLib.UserControlDesigner))]
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
// define a property called "DropZone"
[Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel DropZone
{
get { return panel1; }
}
}
// my designer
public class UserControlDesigner : ParentControlDesigner
{
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
if (this.Control is UserControl1)
{
this.EnableDesignMode(
(UserControl1)this.Control).DropZone, "DropZone");
}
}
}
}
Aprendí esto de Henry Minute en CodeProject. Vea el enlace para algunas mejoras en la técnica.