在设计时将用户控件作为容器 [英] User Control as container at design time

查看:16
本文介绍了在设计时将用户控件作为容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm designing a simple expander control.

我从UserControl派生,绘制内部控件,构建,运行;没事.

I've derived from UserControl, drawn inner controls, built, run; all ok.

由于内部控件是一个面板,我想在设计时将它用作容器.确实我已经使用了这些属性:

Since an inner Control is a Panel, I'd like to use it as container at design time. Indeed I've used the attributes:

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

我说太好了.但这不是……

Great I say. But it isn't...

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

The result is that I can use it as container at design time but:

  • 添加的控件返回已经嵌入用户控件的内部控件
  • 即使我将在设计时添加的控件推到顶部,在运行时它又会返回到嵌入到用户控件的控件上
  • 我无法在设计时将容器区域限制为面板区域

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

What am I missing? Here is the code for completeness... why this snippet of code is not working?

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

我找到了很多资源(交互设计, 有限区域),但没有什么对操作有用...

I've found many resources (Interaction, designed, limited area), but nothing was usefull for being operative...

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

推荐答案

ParentControlDesigner 不知道你想做什么.它只知道您希望您的 UserControl 成为一个容器.

ParentControlDesigner doesn't know what you want do. It only knows you want your UserControl to be a container.

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

What you need to do is implement your own designer which enables design mode on the 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");
                }
            }
        }
    }

我从 CodeProject 上的 Henry Minute 了解到这一点.有关该技术的一些改进,请参阅链接.

I learned this from Henry Minute on CodeProject. See the link for some improvements on the technique.

这篇关于在设计时将用户控件作为容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆