winforms 在设计时将用户控件作为容器

am46iovg  于 2023-08-07  发布在  其他
关注(0)|答案(3)|浏览(143)

我正在设计一个简单的扩展控件。
我已经从UserControl派生,绘制内部控件,构建,运行;一切正常。
由于内部控件是一个面板,我想在设计时使用它作为容器。实际上,我已经使用了属性:

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

字符串
好极了。但这不是...
结果是我可以在设计时将其用作容器,但是:

  • 添加的控件将返回已嵌入用户控件中的内部控件
  • 即使我将在设计时添加的控件推到顶部,在运行时它也会再次回到嵌入到用户控件的控件上
  • 我不能在设计时将容器区域限制为Panel区域

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

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


我已经找到了很多资源(Interactiondesignedlimited area),但没有什么是有用的操作.

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

fafcakar1#

ParentControlDesigner不知道您要做什么。它只知道您希望UserControl成为容器。
你需要做的是实现你自己的设计器,在面板上启用设计模式:

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

字符串
我从CodeProject上的Henry Minute学到了这个。请参阅链接以了解有关该技术的一些改进。

ttisahbt

ttisahbt2#

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

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

字符串
对我来说,这使它足够安全。我们只在内部使用控件,所以我们主要是想防止开发人员意外地拖动东西。反正肯定有办法搞砸的。

qzwqbdag

qzwqbdag3#

要防止工作区在设计器中被移动/调整大小,您必须为该工作区创建一个类,该类对设计器隐藏Location、Height、Width、Size属性:

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

字符串

相关问题