在上一次的尝试中,我们已经可以进行控件的添加了。但后来我发现了一个bug, 就是画好一个控件后,居然还可以接着画出这个控件,这不符合我们的习惯。一般情况下我们希望画好控件后,鼠标变回选择状态。这个功能在.net 2.0以前的做法是实现IToolboxServicevoid SelectedToolboxItemUsed()方法,但是在.net 2.0中我们已经可以用更简单的办法,前面讨论过,在.net 2.0中我们是通过继承ToolboxService类而不是完全实现IToolboxService的方式来简化工具箱功能。分析ToolboxService的源代码,可以看到它已经实现了SelectedToolboxItemUsed()方法, 其代码如下:
void IToolboxService.SelectedToolboxItemUsed()
{
      
this.SelectedItemContainerUsed();
}


protected virtual void SelectedItemContainerUsed()
{
      
this.SelectedItemContainer = null;
}

很显然,它缺省的方式将SelectedItemContainer属性值赋值为null, 这时候我们可以想到一个简便的办法是并不需要重载SelectedItemContainerUsed(), 而是修改SelectedItemContainer属性的set方法,找到上次尝试的代码,在SelectedItemContainer属性的set方法上写上:

if (value == null)
{
    toolBox.SelectedIndex 
= -1;
}

不过后来我觉得还是象vs的工具箱一样,提供一个”Point”的“虚”工具更方便。这个功能只要在我们前面的代码上对几个小地方稍作修改就可以了,就不帖代码了。
接下来的步骤是实现能在PropertyGrid中随意修改任何控件的属性。要做到这点也很简便,只要为DesignSurfaceSelectionService实现一个SelectionChanged事件就行了。
切换到Form1的代码窗口,为窗体类添加一个私有成员:

private ISelectionService selectionService;
然后在Load事件的最后加上:
selectionService = surface.GetService(typeof(ISelectionService)) as ISelectionService;
selectionService.SelectionChanged 
+= new EventHandler(selectionService_SelectionChanged);
当然也为窗体类加上以下事件方法:
void selectionService_SelectionChanged(object sender, EventArgs e)
{
    
object[] selection;
    
if (selectionService.SelectionCount == 0)
        propertyGrid1.SelectedObject 
= null;
    
else
    
{
        selection 
= new object[selectionService.SelectionCount];
        selectionService.GetSelectedComponents().CopyTo(selection, 
0);
        propertyGrid1.SelectedObjects 
= selection;
    }

}

以下是运行时界面:


好象是大功告成了,不过控件只能添加,却怎么删除不了。

当然,还有一些必不可少的功能,如将设计内容序列化到资源文件或者生成代码文件等等。胡适先生说:“自古成功尝试始”,我想一定会在以后几节的尝试中成功实现这些功能的。

相关章节:
Form设计器尝试()
写Form设计器尝试(二) PropertyGrid
写Form设计器尝试(三) 在窗体上添加控件