【转】嵌套子控件设计时支持

转自:点击打开链接

最近在设计一个带标题栏的自定义控件时候,遇到很奇怪的问题——不能向组合控件中添加组件。原以为不存在或是很简单的问题,竟然被拦住好久。这个问题导致的主要问题包括:

1. 不能向组合控件中添加组件。

2. 部分方法如重载OnControlAdded方法等,会导致添加到子容器中的组件设计时或运行时不可见等问题。

虽然最终发现问题很简单,不过在google中没有发现中文的资料(可能搜索水平太差),先将Henry Minute 写在CodeProject的文章标记如此,以作备忘。

答案是在这里找到的,http://stackoverflow.com/questions/2322847/winforms-designer-add-control-and-make-it-visible-for-the-designer

谢谢BillW @stackoverflow.com

If you are dealing with the problem of how a "child" Control of a UserControl placed on a Form at Design-Time can be made to function as a container onto which you can drag-and-drop other controls from the Toolbox : this CodeProject article by Henry Minute may be helpful : Designing Nested Controls. For example : you have a UserControl with a Panel inside it : an instance of the UserControl is placed on a Form : in the Design-time view of the Form : you want to be able to drag-drop controls onto the Panel in the UserControl and have them become child controls of the Panel : Henry's article will show you how to do that.

This from Microsoft : How to make a UserControl object acts as a control container design-time by using Visual C#

解决方案(代码来自Henry Minute):

1. 为自定义控件添加Panel子控件,并将该控件公开。同时将属性的DesignerSerializationVisibility特性设置为DesignerSerializationVisibility.Content.

 

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace NestedControlDesignerLibrary
{
    
/// <summary>
    
/// A test Control to demonstrate allowing nested Controls
    
/// to accept child controls at design time.
    
/// </summary>
    [
    Designer(
typeof(NestedControlDesignerLibrary.Designers.TestControlDesigner))
    ]
    
public partial class TestControl : UserControl
    {
        
public TestControl()
        {
            InitializeComponent();
        }

        
#region TestControl PROPERTIES ..........................
        
/// <summary>
        
/// Surface the Caption to allow the user to 
        
/// change it
        
/// </summary>
        [
        Category(
"Appearance"),
        DefaultValue(
typeof(String), "Test Control")
        ]
        
public string Caption
        {
            
get
            {
                
return this.lblCaption.Text;
            }

            
set
            {
                
this.lblCaption.Text = value;
            }
        }

        [
        Category(
"Appearance"),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        ]
        
/// <summary>
        
/// This property is essential to allowing the designer to work and
        
/// the DesignerSerializationVisibility Attribute (above) is essential
        
/// in allowing serialization to take place at design time.
        
/// </summary>
        public Panel WorkingArea
        {
            
get
            {
                
return this.pnlWorkingArea;
            }
        }
        
#endregion
    }
}
复制代码

 

 2. 自定义设计器。看上面代码中的UserControl的特性。

 

复制代码
namespace NestedControlDesignerLibrary.Designers
{
    
public class TestControlDesigner : ParentControlDesigner
    {
        
public override void Initialize(System.ComponentModel.IComponent component)
        {
            
base.Initialize(component);

            
if (this.Control is TestControl)
            {
                
this.EnableDesignMode((
                   (TestControl)
this.Control).WorkingArea, "WorkingArea");
            }
        }
    }
}
复制代码

 

通过使用EnableDesignMode可以指定要公开的子容器,具体可以看该方法的介绍。如果要添加多个子容器,将其他的都写在这里就好了。

3. 最后的问题,子容器控件被公开,意味着我们可以再设计时更改其属性。虽然也不是完全没用,但很多时候会给人带来困扰,或者改变了原本的组合关系,变的乱糟糟,因此有必要隐藏部分属性,如Dock等。Minute也提到了一些方法。

 

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ImprovedNestedControlDesignerLibrary
{
    [
    Designer(
typeof(ImprovedNestedControlDesignerLibrary.Designers.WorkingAreaDesigner))
    ]
    
public partial class WorkingAreaControl : Panel
    {
        
public WorkingAreaControl()
        {
            InitializeComponent();
            
base.Dock = DockStyle.Fill;
        }
    }
}
复制代码

 

 

就是通过将子容器从Panel继承,在子容器的设计器里面屏蔽Dock属性。

 

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms.Design;

namespace ImprovedNestedControlDesignerLibrary.Designers
{
    
public class WorkingAreaDesigner : ScrollableControlDesigner
    {
        
protected override void PreFilterProperties(
                  System.Collections.IDictionary properties)
        {
            properties.Remove(
"Dock");

            
base.PreFilterProperties(properties);
        }
    }
}
 
依次,可以实现一个能很好的支持子容器控件的UserControl了。
 
------------------------------------------------------------------
来自微软的解释和方案:
默认情况下,UserControl 对象只有在您创建它时才可以用作控件容器。在将 UserControl 放在 Windows 窗体上之后,为让 UserControl 承载构成控件,您必须更改 UserControl 的默认设计器。如要为一个组件实现设计时服务,请使用 System.ComponentModel 名称空间的 DesignerAttribute 类。DesignerAttribute 出现在类声明前面。通过传递 designerTypeName 和 DesignerAttribute 参数初始化 designerTypeName

designerTypeName 是提供设计时服务的设计器类型的完全合格的名称。传递 designerTypeName 参数的System.Windows.Forms.Design.ParentControlDesigner 和 System.Design 的组合。ParentControlDesigner 类扩展了 UserControl 的设计时行为。

designerBaseType 是设计器的基类的名称。用于设计时服务的类必须实现 IDesigner 接口。
 

将 UserControl 创建为设计时控件容器

  1. 创建一个新的 Visual C# .NET Windows 控件库项目。为此,请按照下列步骤操作:
    1. 启动 Visual Studio .NET。
    2. 在“文件”菜单上,指向“新建”,然后单击“项目”。
    3. 在“项目类型”下,单击 “Visual C# 项目”,然后单击“模板”下的 “Windows 控件库”。
  2. 将该项目命名为 ContainerUserControl。默认情况下将创建出 “UserControl1.cs”。
  3. 在解决方案资源管理器中,右键单击 “UserControl1.cs”,然后单击“查看代码”。
  4. 将下面的代码添加到 Declarations 部分:
    using System.ComponentModel.Design;
  5. 如下所示将 System.ComponentModel.DesignerAttribute 属性应用到该控件:
    [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] public class UserControl1 :System.Windows.Forms.UserControl {
    
          ...
    
    }
  6. 在“生成”菜单上,单击“生成解决方案”。

文章内容来自:
微软资料来自于:
隐藏属性的资料:
Shaun Wilde
 
复制代码

 

posted @ 2013-06-29 22:58  爱生活,爱编程  阅读(293)  评论(0编辑  收藏  举报