编写组件自己的设计器
刘志波
简介
什么是设计器?
public interface IDesigner : IDisposable {
IComponent Component {get;}
DesignerVerbCollection Verbs {get;}
void DoDefaultAction();
void Initialize(IComponent component);
}
组件如何和设计器关联?
namespace MyCompany {
[Designer("MyCompany.Design.SysComponentDesigner, MyCompany.Design")]
public class SysComponent : Component {
}
}
namespace MyCompany.Design {
internal class SysComponentDesigner : ComponentDesigner {
// …
}
}
namespace MyCompany {
[Designer(typeof(SysComponentDesigner))]
public class SysComponent : Component {
internal class SysComponentDesigner : ComponentDesigner{
// …
}
}
}
public DesignerVerbCollection GetComponentVerbs(IComponent comp) {
if (comp.Site != null){
IDesignerHost host;
host = comp.Site.GetService(typeof(IDesignerHost));
if (host != null){
IDesigner designer;
designer = host.GetDesigner(comp);
if (designer != null){
return designer.Verbs;
}
}
}
return new DesignerVerbCollection();
}
修改设计时期的状态信息
public class DragDropControlDesigner : ControlDesigner {
public override void Initialize(IComponent c) {
base.Initialize(c);
((Control)c).AllowDrop = false;
}
}
定义组件之间的关系
[Designer(typeof(MainComp.MainCompDesigner))]
public class MainComp : Component {
public SubCompCollection SubComponents {
get {
return subCollection;
}
}
internal class MainCompDesigner : ComponentDesigner {
public override ICollection AssociatedComponents{
get{
return ((MainComp)base.Component).SubComponents;
}
}
}
}
[DesignTimeVisible(false)]
[Designer(typeof(SubComp.SubCompDesigner))]
public class SubComp : Component {
public SubCompCollection SubSubComponents {
get {
return subCollection;
}
}
internal class SubCompDesigner : ComponentDesigner {
public override ICollection AssociatedComponents{
get{
// Only return sited subs in this case.
// For example, this component could have
// a number of sub components that were
// added by the component and aren't sited
// on the design surface. We don't want
// to move those around.
//
ArrayList comps = new ArrayList();
foreach (SubComp sc in
((SubComp)Component).SubSubComponents) {
if (sc.Site != null) {
comps.Add(sc);
}
}
return comps;
}
}
}
}
使用组件自己的设计器来更改组件的属性、特性、事件
public class SimpleControlDesigner : ComponentDesigner {
bool locked;
public bool Enabled {
get {
return (bool)ShadowProperties["Enabled"];
}
set {
// note this value is not passed to the actual
// control
this.ShadowProperties["Enabled"] = value;
}
}
private bool Locked {
get {
return locked;
}
set {
locked = value;
}
}
public bool Visible {
get {
return (bool)ShadowProperties["Visible"];
}
set {
// note this value is not passed to the actual
// control
this.ShadowProperties["Visible"] = value;
}
}
public void Initialize(IComponent c) {
base.Initialize(c);
Control control = c as Control;
if (control == null) {
throw new ArgumentException();
}
// pick up the current state and push it
// into our shadow props to initialize them.
//
this.Visible = control.Visible;
this.Enabled = control.Enabled;
control.Visible = true;
control.Enabled = true;
}
protected override void PreFilterProperties(IDictionary properties) {
base.PreFilterProperties(properties);
// replace Visible and Enabled with our shadowed versions.
//
properties["Visible"] = TypeDescriptor.CreateProperty(
typeof(SimpleControlDesigner),
(PropertyDescriptor)properties["Visible"],
new Attribute[0]);
properties["Enabled"] = TypeDescriptor.CreateProperty(
typeof(SimpleControlDesigner),
(PropertyDescriptor)properties["Enabled"],
new Attribute[0]);
// and add the Locked property
//
properties["Locked"] = TypeDescriptor.CreateProperty(
typeof(SimpleControlDesigner),
"Locked",
typeof(bool),
CategoryAttribute.Design,
DesignOnlyAttribute.Yes);
}
}
简化通常要做的工作
[Designer(typeof(ColorButton.ColorButtonDesigner))]
public class ColorButton : System.Windows.Forms.Button
{
internal class ColorButtonDesigner : ControlDesigner {
private DesignerVerbCollection verbs = null;
private void OnVerbRed(object sender, EventArgs e) {
Control.BackColor = Color.Red;
}
private void OnVerbGreen(object sender, EventArgs e){
Control.BackColor = Color.Green;
}
private void OnVerbBlue(object sender, EventArgs e) {
Control.BackColor = Color.Blue;
}
public override DesignerVerbCollection Verbs {
get {
if (verbs == null) {
verbs = new DesignerVerbCollection();
verbs.Add( new DesignerVerb(
"Red",
new EventHandler(OnVerbRed)));
verbs.Add( new DesignerVerb(
"Blue",
new EventHandler(OnVerbBlue)));
verbs.Add( new DesignerVerb(
"Green",
new EventHandler(OnVerbGreen)));
}
return verbs;
}
}
}
}
与其他组件精确的交互
private void OnVerbGreen(object sender, EventArgs e){
PropertyDescriptor backColorProp =
TypeDescriptor.GetProperties(Control)["BackColor"];
if (backColorProp != null) {
backColorProp.SetValue(Control, Color.Green);
}
}
internal class RadioButtonDesigner : ControlDesigner {
public bool Checked {
get {
// pass the get down to the control.
//
return ((RadioButton)Control).Checked;
}
set {
// set the value into the control
//
((RadioButton)Control).Checked = value;
// if the value for this radio button
// was set to true, notify that others have changed.
//
if (value) {
IComponentChangeService ccs =
(IComponentChangeService)
GetService(typeof(IComponentChangeService));
if (ccs != null) {
PropertyDesciptor checkedProp =
TypeDescriptor.GetProperties(typeof(RadioButton))["Checked"];
foreach(RadioButton rb in
Control.Parent.Controls) {
if (rb == Control || !(rb is RadioButton))
continue;
ccs.OnComponentChanging(rb, checkedProp);
ccs.OnComponentChanged(rb,chedkedProp, null, null);
}
}
}
}
}
protected override void PreFilterProperties(
IDictionary properties) {
base.PreFilterProperties(properties);
// shadow the checked property so we can intercept the set.
//
properties["Checked"] =
TypeDescriptor.CreateProperty( typeof(RadioButtonDesigner),
(PropertyDescriptor)properties["Checked"],
new Attribute[0]);
}
}
结论