Visual Studio 2010***的卖点就是可扩展性。这样就可以借助.NET社区的力量基于VS构建出许多有用的工具。本文中我们将展示如何扩展VS2010的服务器资源管理器,在其中的SharePoint结点上添加一个自定义操作。
SharePoint服务器资源管理器是Visual Studio 2010的一项新特性,该功能是由Visual Studio Tools for SharePoint提供的。
如果你只需要从Visual Studio中浏览SharePoint站点里的内容(网站栏,内容类型,功能等),那么默认功能对你来说就已经非常好用了。 然而,在默认情况下,SharePoint服务器资源管理器除了可以显示网站里有哪些可用的内容以外,其它什么也做不了。
正如你所看到的,上下文菜单中仅有很少的几项。下图是通知列表的属性面板。 该属性存储在Annotations中。为了方便理解什么是Annotation,你可以把它们想象成一个带属性的类。这些属性就是我们在下面的属性面板中看到的:
这里还是只读的。
我可以扩展吗?
接下来你一定会问这样一个问题(如果你是一名SharePoint开发人员的话)——我能不能对其进行扩展,向SharePoint服务器资源管理器中添加自定义的命令或结点呢?
答案是肯定的。你可以扩展SharePoint服务器资源管理器,包括:
1)创建新结点
2)扩展已有结点
给我个例子好吗?
让我们以功能结点为例。
功能结点下显示了该网站下所有已激活的功能。如果右击某个功能,你会看到少得可怜的几项。
如果能在上下文菜单中添加一项“停用”,点击可以停用选中的功能,那就太帅了:)
[顺带说一句,这张截图是实实在在的做好的扩展,而非Photoshop出来的:)]
理解SharePoint服务器资源管理器
在正式开始编写一个扩展之前,你必须了解一下SharePoint服务器资源滚利器中不同类型的结点:
本例中我们感兴趣的是FeatureNode。
开始
MSDN上有一篇非常棒的文章介绍了如何扩展Visual Studio Tools for SharePoint
下图是我们将要进行的工作的图形化表示:
1、新建一个类,并实现IExplorerNodeTypeExtension接口
2、处理事件
3、通过Annotations 访问该结点的属性
4、通过客户端对象模型执行SharePoint操作
***步
创建一个Windows类库项目并添加下列引用
第二步
创建一个类并实现接口IExplorerNodeTypeExtension:
第三步
我们感兴趣的是在上下文菜单中添加一项,处理事件NodeMenuItemsRequested。这些都在Initialize方法中完成:
- public void Initialize(IExplorerNodeType nodeType)
- {
- nodeType.NodeMenuItemsRequested +=
- new EventHandler<ExplorerNodeMenuItemsRequestedEventArgs>
- (nodeType_NodeMenuItemsRequested);
- }
在下面添加事件处理程序:
- void nodeType_NodeMenuItemsRequested(object sender, ExplorerNodeMenuItemsRequestedEventArgs e)
- {
- IMenuItem deactivateMenu = e.MenuItems.Add("停用");
- deactivateMenu.Click +=
- new EventHandler<MenuItemEventArgs>(deactivateMenu_Click);
- }
我们在事件处理程序中添加了一个菜单项并且处理了其自身的点击事件。
第四步
我们若要停用一个功能,首先需要知道该功能的Definition Id。在功能的属性面板中已经有这个值了:
为了访问该属性,我们需要借助于Annotations对象。下面是访问功能属性的代码:
- IFeatureNodeInfo fn = e.Node.Annotations[typeof(IFeatureNodeInfo)] as IFeatureNodeInfo;
- definitionId = fn.Id;
- featureName = fn.Name;
接下来我们要获取该功能所处的网站。因为服务器资源管理器已经实例化了到该站点的连接,因此我们可以直接从当前上下文中获取。
- IExplorerNodeContext siteContext = e.Node.Context;
下面是事件处理程序代码现在的样子:
- void nodeType_NodeMenuItemsRequested(object sender, ExplorerNodeMenuItemsRequestedEventArgs e)
- {
- siteContext = e.Node.Context;
- IFeatureNodeInfo fn = e.Node.Annotations[typeof(IFeatureNodeInfo)] as IFeatureNodeInfo;
- definitionId = fn.Id;
- featureName = fn.Name;
- IMenuItem deactivateMenu = e.MenuItems.Add("停用");
- deactivateMenu.Click += new EventHandler<MenuItemEventArgs>(deactivateMenu_Click);
- }
第五步
现在我们可以通过客户端对象模型在新菜单项的事件处理程序中编写停用功能的代码了:
- void deactivateMenu_Click(object sender, MenuItemEventArgs e)
- {
- if (MessageBox.Show(confirmationMessage,String.Format("停用{0} 功能",featureName),
- MessageBoxButtons.YesNo,
- MessageBoxIcon.Exclamation) == DialogResult.Yes)
- {
- IExplorerNode parentFeatureNode = e.Owner as IExplorerNode;
- IExplorerNode featureNode = parentFeatureNode.ParentNode;
- ClientContext clientContext = new ClientContext(siteContext.SiteUrl.AbsoluteUri);
- Web site = clientContext.Web;
- FeatureCollection siteFeatures = site.Features;
- clientContext.Load(site, s => s.Title, s => s.Features);
- siteFeatures.Remove(definitionId, false);
- clientContext.ExecuteQuery();
- clientContext.Dispose();
- featureNode.Refresh();
- }
- }
确实很简单。查询并仅返回Web和Features对象,然后从该站点中Remove(停用)该功能。
你也可以通过客户端对象模型的异步模式来实现异步调用。
部署该扩展
为了能够部署这个扩展,我们需要将其包含到一个.vsix包中。
你可以套用VSIX模板来创建.vsix包。
在manifest文件中包含该扩展。
选择内容为MEF Component,并选择扩展项目作为源。
编译该项目并生成相应的.vsix包,然后安装这个包。
为FeatureNode所开发的“停用扩展”就完成了
现在看看上下文菜单,已经出现我们的菜单项了:
当你点击它时,会弹出确认消息:
点"是"的话将停用该功能并刷新功能结点树视图。