这是个非常简单的例子,演示了用ISelectionService来获得当前组件,并用PropertyGrid来编辑该组件。
也演示了锁定、复制、删除、移到上层等简单操作,以及在锁定的状态下禁止一些操作。
虽然例子本身非常简单,但设计器本身是个非常大的议题,因此代码将分两部分贴出。
有兴趣的朋友们还可以参考:Windows Forms Programming: Design-Time Architecture
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
DesignSurface designSurface;
IDesignerHost formDesignerHost;
public Form1()
{
InitializeComponent();
InitializeDesignerSurface();
InitializeListBox();
this.propertyGrid1.SelectedObject = this.formDesignerHost.RootComponent;
}
private void InitializeDesignerSurface()
{
this.designSurface = new System.ComponentModel.Design.DesignSurface(typeof(Form));
Control view = this.designSurface.View as Control;
this.tableLayoutPanel1.Controls.Add(view, 0, 0);
this.tableLayoutPanel1.SetRowSpan(view, 2);
view.Dock = DockStyle.Fill;
this.formDesignerHost = this.designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
this.formDesignerHost.AddService(typeof(INameCreationService), new MyNameService());
ISelectionService selectionService = this.formDesignerHost.GetService(typeof(ISelectionService)) as ISelectionService;
selectionService.SelectionChanged += delegate
{
System.Collections.ICollection collection = selectionService.GetSelectedComponents();
object[] selectedObjects = new object[collection.Count];
collection.CopyTo(selectedObjects, 0);
this.propertyGrid1.SelectedObjects = selectedObjects;
};
}
private void InitializeListBox()
{
this.listBox1.DisplayMember = "Name";
this.listBox1.DataSource = new Type[]
{
typeof(Label), typeof(Button), typeof(TextBox), typeof(RadioButton),typeof(CheckBox),
};
this.listBox1.DoubleClick += delegate
{
CreateControl(this.listBox1.SelectedItem as Type);
};
}
private void CreateControl(Type controlType)
{
if (typeof(Control).IsAssignableFrom(controlType) && !typeof(Form).IsAssignableFrom(controlType))
{
Control control = this.formDesignerHost.CreateComponent(controlType) as Control;
control.Text = control.Name;
control.Location = new Point(5, System.Environment.TickCount % 200);
(this.formDesignerHost.RootComponent as Form).Controls.Add(control);
}
}
private void btnLock_Click(object sender, EventArgs e)
{
foreach (IComponent component in this.propertyGrid1.SelectedObjects)
{
PropertyDescriptor lockedProperty = TypeDescriptor.GetProperties(component)["Locked"];
if (lockedProperty != null)
{
lockedProperty.SetValue(component, true);
this.propertyGrid1.Refresh();
}
}
}
private void btnCopy_Click(object sender, EventArgs e)
{
Control control = this.propertyGrid1.SelectedObject as Control;
if (control != null) CreateControl(control.GetType());
}
private void btnDelete_Click(object sender, EventArgs e)
{
foreach (IComponent component in this.propertyGrid1.SelectedObjects)
{
if (component is Form == false && !IsLocked(component))
{
this.formDesignerHost.DestroyComponent(component);
}
}
}
private void btnBringforward_Click(object sender, EventArgs e)
{
Control control = this.propertyGrid1.SelectedObject as Control;
if (control != null && !IsLocked(control) ) control.BringToFront();
}
private bool IsLocked(IComponent component)
{
PropertyDescriptor lockedProperty = TypeDescriptor.GetProperties(component)["Locked"];
if (lockedProperty != null) return (bool)lockedProperty.GetValue(component);
return false;
}
}
class MyNameService : INameCreationService
{
static int s_i = 0;
public string CreateName(IContainer container, Type dataType)
{
return dataType.Name + s_i++;
}
public bool IsValidName(string name)
{
if (string.IsNullOrEmpty(name) == true) return false;
if (char.IsDigit(name[0])) return false;
foreach(char ch in name)
{
if (char.IsLetterOrDigit(ch) == false && ch != '_') return false;
}
return true;
}
public void ValidateName(string name)
{
if (!IsValidName(name)) throw new Exception("Invalid name");
}
}
}
C# code
// Form1.Designer.cs
namespace WindowsFormsApplication1
{
partial class Form1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.btnBringforward = new System.Windows.Forms.Button();
this.btnDelete = new System.Windows.Forms.Button();
this.btnCopy = new System.Windows.Forms.Button();
this.btnLock = new System.Windows.Forms.Button();
this.listBox1 = new System.Windows.Forms.ListBox();
this.tableLayoutPanel1.SuspendLayout();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 300F));
this.tableLayoutPanel1.Controls.Add(this.propertyGrid1, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.groupBox1, 1, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 70F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 30F));
//
// propertyGrid1
//
this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.listBox1);
this.groupBox1.Controls.Add(this.btnBringforward);
this.groupBox1.Controls.Add(this.btnDelete);
this.groupBox1.Controls.Add(this.btnCopy);
this.groupBox1.Controls.Add(this.btnLock);
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Double click the listbox to add control";
//
// btnBringforward
//
this.btnBringforward.Location = new System.Drawing.Point(6, 138);
this.btnBringforward.Size = new System.Drawing.Size(136, 35);
this.btnBringforward.TabIndex = 1;
this.btnBringforward.Text = "&Bring Forward";
this.btnBringforward.Click += new System.EventHandler(this.btnBringforward_Click);
//
// btnDelete
//
this.btnDelete.Location = new System.Drawing.Point(6, 100);
this.btnDelete.Size = new System.Drawing.Size(136, 35);
this.btnDelete.TabIndex = 2;
this.btnDelete.Text = "&Delete";
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
//
// btnCopy
//
this.btnCopy.Location = new System.Drawing.Point(7, 62);
this.btnCopy.Size = new System.Drawing.Size(135, 35);
this.btnCopy.TabIndex = 3;
this.btnCopy.Text = "&Copy";
this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click);
//
// btnLock
//
this.btnLock.Location = new System.Drawing.Point(7, 21);
this.btnLock.Size = new System.Drawing.Size(135, 35);
this.btnLock.TabIndex = 4;
this.btnLock.Text = "&Lock";
this.btnLock.Click += new System.EventHandler(this.btnLock_Click);
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.ItemHeight = 16;
this.listBox1.Location = new System.Drawing.Point(149, 22);
this.listBox1.Size = new System.Drawing.Size(139, 148);
this.listBox1.TabIndex = 2;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(963, 616);
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "Form1";
this.Text = "Designer Host";
this.tableLayoutPanel1.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.PropertyGrid propertyGrid1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button btnBringforward;
private System.Windows.Forms.Button btnDelete;
private System.Windows.Forms.Button btnCopy;
private System.Windows.Forms.Button btnLock;
private System.Windows.Forms.ListBox listBox1;
}
}