.net 2.0以前的版本中想实现在窗体设计器中添加控件的做法是定义一个实现IToolboxService接口的“服务”,然后添加到ServiceContainer中,具体方式可以参照http://www.divil.co.uk/net/articles/designers/hosting.asp 。这个地址在www.windowsforms.net Code hero中也可以找到。

.net 2.0简化了这个作业,它已经为我们提供了一个实现IToolboxService接口的抽象类ToolboxService,我们要做的就是写一个类继承自ToolboxService, 要简便很多。

具体操作是新建一个继承自ToolboxService的类,名为DemoToolboxService, 加上必要的using语句,在所继承的类名上按鼠标右键,点“Implement Abstract Class,已经帮我们自动完成了DemoToolboxService的框架,由于我们需要在设计器窗体上显示一个工具箱,就象VS左侧的那个工具面板,不过我们现在做一个简单一点的,就用ListBox, DemoToolboxService中添加一个类型为ListBox的私有成员,并封装成属性。稍微改动一下,实现几个必要的方法,代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms;

namespace FormDesigner
{
    
class DemoToolboxService :ToolboxService
    
{

        
private ListBox toolBox;

        
public ListBox ToolBox
        
{
            
get return toolBox; }
            
set { toolBox = value; }
        }


        
protected override CategoryNameCollection CategoryNames
        
{
            
get
            
{
                
return null;
            }

        }


        
//实现带分类的工具列表,由于目前不分类,所以即为全部工具
        protected override System.Collections.IList GetItemContainers(string categoryName)
        
{
            ToolboxItem[] t 
= new ToolboxItem[this.toolBox.Items.Count];
            
this.toolBox.Items.CopyTo(t, 0);

            
return t;
        }


        
//实现工具列表
        protected override System.Collections.IList GetItemContainers()
        
{
            ToolboxItem[] t 
= new ToolboxItem[this.toolBox.Items.Count];
            
this.toolBox.Items.CopyTo(t, 0);

            
return t;
        }


        
protected override void Refresh()
        
{
        }


        
protected override string SelectedCategory
        
{
            
get
            
{
                
return null;
            }

            
set
            
{
            }

        }


        
//实现工具选择
        protected override ToolboxItemContainer SelectedItemContainer
        
{
            
get
            
{
                
if (toolBox.SelectedIndex > 0)
                
{
                    
return new ToolboxItemContainer((ToolboxItem)toolBox.SelectedItem);
                }

                
return null;
            }

            
set
            
{
            }

        }

    }

}


   

切换到主Form的设计界面,在那个SplitContainer左侧再放上一个Panel, 做为将要完成的工具箱的容器,再切换到Form的代码编辑界面,添加一个类型为DemoToolService的私有成员toolBoxService, 修改Load事件代码,加上以下语句:

toolBoxService = new DemoToolboxService();

toolBoxService.ToolBox 
= new ListBox();

toolBoxService.ToolBox.Items.Add(
new ToolboxItem(typeof(Button)));
toolBoxService.ToolBox.Items.Add(
new ToolboxItem(typeof(TextBox)));
toolBoxService.ToolBox.Items.Add(
new ToolboxItem(typeof(Label)));
toolBoxService.ToolBox.Items.Add(
new ToolboxItem(typeof(TabControl)));
toolBoxService.ToolBox.Items.Add(
new ToolboxItem(typeof(StatusBar)));

toolBoxService.ToolBox.Dock 
= DockStyle.Fill;
this.panel1.Controls.Add(toolBoxService.ToolBox);

IServiceContainer container 
= surface.GetService(typeof(IServiceContainer)) as IServiceContainer;

 
if (container != null)
{
container.AddService(
typeof(IToolboxService), toolBoxService);
}

  运行方案,并试着在所设计的窗体上加上几个控件,界面如下:

 
 
我们画呀画,很有成就感了,但是左侧的工具箱也太丑了一点,右边那个PropertyGrid居然不因我们选择了不同的控件而改变,一点都不听话。

但无论怎样,到现在为止,我们写的代码也只有30行左右。

相关章节:
Form设计器尝试()
写Form设计器尝试(二) PropertyGrid

下节预告:Form设计器尝试() 修改窗体上的控件属性