代码之家  ›  专栏  ›  技术社区  ›  Luca

设计时作为容器的用户控件

  •  17
  • Luca  · 技术社区  · 14 年前

    我正在设计一个简单的扩展器控件。

    我从UserControl派生,绘制内部控件,构建,运行;一切正常。

    由于内部控件是一个面板,所以我希望在设计时将其用作容器。实际上,我使用了以下属性:

    [Designer(typeof(ExpanderControlDesigner))]
    [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] 
    

    很好,我说。但不是…

    结果是我可以在设计时将其用作容器,但是:

    • 添加的控件将返回已嵌入用户控件中的内部控件
    • 即使我将在设计时添加的控件推到最上面,在运行时它也会重新回到嵌入到用户控件中的控件上。
    • 我不能在设计时将集装箱区域限制为面板区域

    我错过了什么?这是完整性的代码…为什么这段代码不起作用?

    [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;
            }
        }
    }
    

    我找到了很多资源( Interaction , designed , limited area 但是没有什么对手术有用的…

    实际上有一个诀窍,因为System.Windows.Forms类可以(像往常一样)设计,并且在运行时具有正确的行为(例如TabControl)。

    3 回复  |  直到 6 年前
        1
  •  17
  •   Larry    12 年前

    ParentControlDesigner不知道您要做什么。它只知道您希望用户控件是一个容器。

    您需要做的是实现自己的设计器,它在面板上启用设计模式:

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

    我从中学到这个 Henry Minute 在代码项目上。有关该技术的一些改进,请参见链接。

        2
  •  3
  •   philip    12 年前

    除了上面的答案。注释中提到,用户可以拖动工作区域。我的解决方法是在另一个面板中包含WorkingArea面板,将其设置为Dock.Fill。为了禁止用户更改它,我创建了一个类ContentPanel,它覆盖并隐藏Dock属性:

    class ContentPanel : Panel
    {
        [Browsable(false)]
        public override DockStyle Dock
        {
            get { return base.Dock; }
            set { base.Dock = DockStyle.Fill; }
        }
    }
    

    对我来说,这就足够安全了。我们只在内部使用控件,因此我们主要希望防止开发人员意外地拖拽东西。无论如何,肯定有办法把事情搞砸。

        3
  •  3
  •   Jens Meinecke    11 年前

    要防止工作区在设计器中被移动/调整大小,必须为该工作区创建一个类,该类从设计器中隐藏位置、高度、宽度、大小属性:

    public class WorkingArea : Panel
    {
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Point Location
        {
            get
            {
                return base.Location;
            }
            set
            {
                base.Location = value;
            }
        }
    ...
    }