• 嵌套子控件的设计时支持


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

    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 出现在类声明前面。通过传递 designerTypeNameDesignerAttribute 参数初始化 designerTypeName

    designerTypeName 是提供设计时服务的设计器类型的完全合格的名称。传递 designerTypeName 参数的 System.Windows.Forms.Design.ParentControlDesignerSystem.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
     
  • 相关阅读:
    L208
    L207
    L206
    L205 EE
    L204
    监控glusterfs
    监控elssticSearch健康状态
    防火墙
    创建逻辑卷
    编译安装nginx,并使用systemd管理nginx
  • 原文地址:https://www.cnblogs.com/tukzer/p/DesignNestedControl.html
Copyright © 2020-2023  润新知