[英]How to force a certain UserControl design
我正在编写一个基本的UserControl,它将被一堆其他UserControl继承。 我需要为所有这些后代控件强制执行某种设计(例如,几个按钮必须在顶部以及一个或两个标签)。
子孙UserControl区域的其余部分可以自由放置任何内容。
最初,我认为我可以将面板放到基本UserControl上,设置Dock = Fill,后代控件的设计者将被迫将所有UI添加到该面板中。 然后,我可以将面板调整为适合我的内容的大小。
事实并非如此-将控件(例如GridView)放到后代UserControl上时,它将它添加到后代用户控件的.Controls集合中,而不是我添加的Panel中。
有没有办法从基本用户控件中强制某种布局?
简短的答案是“是”。但是,要使这种行为深入研究编写自己的设计器的丑陋世界,您必须将其与每个控件相关联,这需要将特殊位置继承到内容面板中。
以下链接应该是一个很好的起点,因为它概述了需要完成的工作并提供了示例代码。
http://support.microsoft.com/?id=813808
被警告,但是,这不是一件容易的事。 并且有很多代码(30多个文件)可供筛选,以了解如何实现设计器。 自从我尝试过大约两年了。
另一方面,您是否考虑过将设计更改为具有一个带有标签和按钮的单个父控件,并使用适当的子控件填充内容区域? 也许甚至让您的孩子对内容区域进行控制都实现了一个特定的接口来保证合同,以便家长可以与他们进行交互而不必知道特定的类名?
AngryHacker-
我以为这很容易,然后发现自己踏上了进入WinForm设计时领域的有趣旅程。 这绝对不像在VB6中那么容易:-)。
无论如何,经过一番研究,我发现了许多对名为EnableDesignMode()的方法的引用。 但是,这不能从WinForm组件直接访问。 这必须从ParentControlDesigner子类的类中调用,该类通过Designer属性注入到UserControl中。 在这个项目中,我调用了子类ButtonBarDesigner ,并且重写了Initialize()方法,该方法使我可以告诉设计器ButtonBar组件具有子组件fillPanel ,可以通过公共属性“ FillPanel”对其进行访问。
在这一点上,它似乎正在工作。 我设法将一个控件放到ButtonBar上,它出现在填充面板中。 但是,如果您保存了表单,然后重新加载了表单,事实证明该控件已实例化,但未放置在ButtonBar控件中。 似乎有一点偷偷摸摸的地方, EnableDesignMode()的文档方便地省略了这一点。 您需要在FillPanel属性上具有DesignerSerializationVisibility属性。 添加此属性即可完成这项工作。
您需要在项目中引用System.Design才能使设计时工作正常。
以下代码用于假定的基类ButtonBar:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Threading;
namespace ForceUserControl
{
[Designer(typeof(ButtonBarDesigner))]
public partial class ButtonBar : UserControl
{
public ButtonBar()
{
InitializeComponent();
}
/// <summary>
/// Returns inner panel.
/// </summary>
/// <remarks>Should allow persistence.</remarks>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel FillPanel
{
get { return fillPanel; }
}
}
private class ButtonBarDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
Panel fillPanel = ((ButtonBar)component).FillPanel;
// The name should be the same as the public property used to return the inner panel control.
base.EnableDesignMode(fillPanel, "FillPanel");
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.