现在的位置: 首页 > 综合 > 正文

实现类似“添加扩展程序…”的设计时支持

2011年07月23日 ⁄ 综合 ⁄ 共 5503字 ⁄ 字号 评论关闭

    Ajax Control Toolkit这个控件库内包含一些扩展控件,利用这些扩展控件,可以非常方便的为普通的控件添加Ajax效果,例如,利用AutoCompleteExtender控件,可以为文本框添加自动完成的ajax效果。当然,这并不是本文想讨论的内容。

    将Ajax Control Toolkit加入到Visual Studio 2008的工具箱中,并打开一个新的aspx文件,向里面拖入一个TextBox。这时,有趣的事情发生了,在TextBox的SmartTasks面板里,竟然出现了一个“添加扩展程序…”的链接!我又试着拖入一个Button,一个Panel,无一例外的,每个控件的SmartTasks面板的底部都出现了“添加扩展程序…”的链接。

    最近我正打算把保存、删除、关闭页面等功能抽象成动作,每一种动作对应一个自定义的Web控件,将某个动作控件附加到目标控件(例如Button)上面之后,目标控件就拥有了诸如保存、删除、关闭页面的功能。如何在WebForm设计器里为一个Button控件方便地附加动作?我想要的正是类似“添加扩展程序…”这样的效果。

    开发过自定义服务器控件的朋友应该知道,如果想给控件添加SmartTasks,需要重写ControlDesigner的ActionLists属性,并实现自己的DesignerActionList。显然,一个TextBox并不知道AjaxControlToolkit的存在,所以“添加扩展程序…”这么一个DesignerActionMethodItem并不是它加进来的。那么,.net framework是否提供了某种接口,可以让我们为别的控件“动态的注入”DesignerActionItem呢?

    通过对AjaxControlToolKit.dll的研究,我发现这些扩展控件的Designer并不负责提供“添加扩展程序”这个Action,他们只负责提供相应扩展程序对应的扩展内容,所以只能从Visual studio的webform designer作为入口来研究。用reflector打开Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.Web.Design.Client.dll,找到了IWebSmartTasksProvider接口,该接口有一个GetDesignerActionLists的方法,这个方法的返回值应该就是SmartTasks面板里显示的内容了。这个接口有3个实现类,DataFormDesignerDataFormXslValueOfDesignerElementDesigner。从这三个类的命名上可以推断,ElementDesigner应该是用的最多的实现类了。ElementDesigner的GetDesignerActionLists的方法实现如下:

   1: DesignerActionListCollection IWebSmartTasksProvider.GetDesignerActionLists()

   2: {

   3:     DesignerActionListCollection componentActions = null;

   4:     if (this.Designer != null)

   5:     {

   6:         DesignerActionService service = (DesignerActionService) base.DesignerHost.GetService(typeof(DesignerActionService));

   7:         if (service != null)

   8:         {

   9:             componentActions = service.GetComponentActions(this.Designer.Component);

  10:         }

  11:     }

  12:     if (componentActions == null)

  13:     {

  14:         componentActions = new DesignerActionListCollection();

  15:     }

  16:     return componentActions;

  17: }

  18:  

  19:  

  20:  

  21:  

    从上面代码里可以看到最终的DesignerActionListCollection是由System.Design程序集下的System.ComponentModel.Design.DesignerActionService类的GetComponentActions决定的,Microsoft.Web.Design.Client.dll下的Microsoft.Web.Design.WebFormDesigner+WebDesignerActionService继承了该类,他的实现如下:

   1: protected override void GetComponentDesignerActions(IComponent component, DesignerActionListCollection actionLists)

   2: {

   3:     Control control = component as Control;

   4:     ElementDesigner parent = null;

   5:     if (control != null)

   6:     {

   7:         parent = ElementDesigner.GetElementDesigner(control);

   8:     }

   9:     if ((parent == null) || !parent.InTemplateMode)

  10:     {

  11:         base.GetComponentDesignerActions(component, actionLists);

  12:         if ((parent != null) && (parent.Designer != null))

  13:         {

  14:             ControlDesigner designer = parent.Designer as ControlDesigner;

  15:             if ((designer != null) && (designer.AutoFormats.Count > 0))

  16:             {

  17:                 actionLists.Insert(0, new AutoFormatActionList(parent));

  18:             }

  19:         }

  20:         if ((parent != null) && (parent.Element != null))

  21:         {

  22:             IWebDataFormElementCallback dataFormElementCallback = parent.Element.GetDataFormElementCallback();

  23:             if (dataFormElementCallback != null)

  24:             {

  25:                 DataFormElementActionList list = new DataFormElementActionList(parent, parent.Control, dataFormElementCallback);

  26:                 actionLists.Add(list);

  27:                 DataFormElementActionList.ModifyActionListsForListControl(actionLists, list);

  28:             }

  29:         }

  30:         if (((parent != null) && (parent.Designer != null)) && parent.DocumentDesigner.ExtenderControlHelper.ProvidesActionLists)

  31:         {

  32:             parent.DocumentDesigner.ExtenderControlHelper.AddActionLists(parent, actionLists);

  33:         }

  34:     }

  35:     if ((parent != null) && (parent.TemplateEditingUI != null))

  36:     {

  37:         actionLists.Add(new TemplateEditingActionList(parent.TemplateEditingUI, parent.Element));

  38:     }

  39: }

  40:  

  41:  

  42:  

  43:  

    这个方法里,有这么一段:

   1: if (((parent != null) && (parent.Designer != null)) && parent.DocumentDesigner.ExtenderControlHelper.ProvidesActionLists)

   2:        {

   3:            parent.DocumentDesigner.ExtenderControlHelper.AddActionLists(parent, actionLists);

   4:        }

    看来“添加扩展程序”这个action就是在这里加进去的了。继续查看ExtenderControlHelper.AddActionLists的实现:

   1: public void AddActionLists(ElementDesigner element, DesignerActionListCollection lists)

   2: {

   3:     lists.Add(new ControlExtenderActionList(element));

   4:     ExtenderControl component = element.Designer.Component as ExtenderControl;

   5:     Control control = element.Designer.Component as Control;

   6:     if ((component == null) && (control != null))

   7:     {

   8:         IExtenderInformationService service = (IExtenderInformationService) control.Site.GetService(typeof(IExtenderInformationService));

   9:         if (service != null)

  10:         {

  11:             foreach (Control control3 in service.GetAppliedExtenders(control))

  12:             {

  13:                 lists.Add(new HoistedExtenderActionList(element.Designer, control3));

  14:             }

  15:         }

  16:     }

  17: }

  18:  

  19:  

  20:  

  21:  

    这个方法里的第一句是lists.Add(new ControlExtenderActionList(element)),ControlExtenderActionList继承了System.ComponentModel.Design.DesignerActionList,他的GetSortedActionItems方法定义如下:

   1: public override DesignerActionItemCollection GetSortedActionItems()

   2: {

   3:     Control component = (Control) this._htmlDesigner.Component;

   4:     DesignerActionItemCollection items = new DesignerActionItemCollection();

   5:     IExtenderInformationService service = (IExtenderInformationService) component.Site.GetService(typeof(IExtenderInformationService));

   6:     string category = SR.GetString(SR.Ids.SmartTasksLabelExtenderSection, CultureInfo.CurrentUICulture);

   7:     if (service.IsControlExtendible(component))

   8:     {

   9:         string displayName = SR.GetString(SR.Ids.SmartTasksAddExtender, CultureInfo.CurrentUICulture);

  10:         items.Add(new DesignerActionMethodItem(this, "AddExtender", displayName, category, true));

  11:     }

  12:     if (service.IsControlExtended(component))

  13:     {

  14:         string str3 = SR.GetString(SR.Ids.SmartTasksRemoveExtender, CultureInfo.CurrentUICulture);

  15:         items.Add(new DesignerActionMethodItem(this, "RemoveExtender", str3, category, true));

  16:     }

  17:     return items;

  18: }

  19:  

    这下清楚了,“添加扩展程序”这个action,是在Visual studio的web form设计器里,写死进去的,.net framework并没有提供相应接口来供我们添加类似的action。但是我想要的效果是增加一个“添加动作”的action,所以我不能参考AjaxControlToolkit的方法去实现,应该要寻找别的方法。

    回过

抱歉!评论已关闭.