这篇博客从一个研发的视角,结合SharePoint Designer和Reflector讲一下SharePoint的表单(Form)是如何工作的。
以打开一个自定义列表List1作为例子,List1只有一个content type是item content type,因此只有一列Title。对List1中的item进行操作的时候,事实上是用到了三个form:new form,edit form和display form。 new form就是新建一个item的时候使用的form:
edit form就是编辑一个item的时候使用的form:
display form就是展示一个item的时候使用的form:
如果使用SharePoint designer打开List1,可以看到这三个form,对应的名字依次是NewForm.aspx, EditForm.aspx和DispForm.aspx。
这几个apsx页面是在列表创建的时候就创建好的,但这几个页面不是应用程序页面(application page),没有保存在layouts文件夹下,而是保存在内容数据库中,通过SharePoint Designer可以查看它们,如果使用Designer依次打开,可以发现,它们都包含一个ListFormWebPart:
这个ListFormWebPart负责展示不同的form。下面打开reflector,看一看ListFormWebPart是如何工作的。ListFormWebPart的一个重要的属性是“Template”,这个属性负责获取一个用于展示form的template:
这里用到了另一个属性“TemplateName”,这个属性会根据当前的页面是new, edit还是display,来返回item的content type中指定的template的名字:
... ... SPContentType contentType = this.ItemContext.ContentType; if (contentType != null) { switch (this.pageType) { case PAGETYPE.PAGE_DISPLAYFORM: this.templateName = contentType.DisplayFormTemplateName; //如果当前页面是display,返回DisplayFormTemplateName break; case PAGETYPE.PAGE_EDITFORM: this.templateName = contentType.EditFormTemplateName; //如果当前页面是edit,返回EditFormTemplateName break; case PAGETYPE.PAGE_NEWFORM: this.templateName = contentType.NewFormTemplateName; //如果当前页面是new,返回NewFormTemplateName break; } if ((this.templateName != null) && (this.templateName.Length > 0)) { return this.templateName; } ... ...
对于item这个content type来说,这三个属性的值都是ListForm。现在ListFormWebPart得到了template的名字,那么这个template在哪儿呢?这个template就定义在layouts文件夹下的DefaultTemplate.ascx文件中,这个文件定义了很多template,ListForm只是其中的一个,例如TaskForm,BlogForm等等:
ListFormWebPart最后载入的是这个template,然后在CreateChildControl的方法中初始化了其中定义的各个控件:
protected override void CreateChildControls() { ... ... this.Controls.Clear(); TemplateContainer container = new TemplateContainer { ControlMode = PageTypeToControlMode(this.pageType), ItemContext = this.ItemContext }; this.Template.InstantiateIn(container); this.Controls.Add(container); ... ... }
这样SharePoint就通过ListFormWebPart完成了不同的form的展示。但是一个问题是,虽然用的是一个模板,但是为什么最终展示的东西确是不同的?new form展示出来一个文本框,而display form却展示出来一个label?这是由于最终展示column的控件,是“ListFieldIterator”,这个控件负责最后的column的展示。
以上就是SharePoint在打开一个form的时候做的事情,知道这些有什么用呢?第一,可以自定义template,覆盖SharePoint的template,可以参考这篇文章。第二,可以知道如何在定义自己的content type的时候,指定自己的template。