首页 > 代码库 > 列表操作 - C#开发人员
列表操作 - C#开发人员
| SharePoint 2013开发入门探索(二)- 列表操作 我们如何用代码对SharePoint列表做些例如增删改查的操作呢?如果您的程序可以部署到服务器上,就可以使用 服务器对象模型,因为服务器对象模型提供的功能最多,限制最少;否则可能要选择客户对象模型等其他方式,这可能会遇到一些功能限制;另外还有一些其他的访问方式,例如Web服务等。如何在 SharePoint 2013 中选择正确的 API 集请参考链接http://msdn.microsoft.com/zh-cn/library/jj164060.aspx 。 我们首先研究下服务器对象模型。使用服务器对象模型需要到服务器端部署,所以没有服务器部署权限的话就不能使用了。使用服务对象模型要引用程序集Microsoft.SharePoint —— 如果您创建的是SharePoint项目,这个引用默认就会有的。 在服务器对象模型中我经常使用的几个.NET类是SPSite、SPWeb、SPList还有SPListItem,下面简单介绍下这几个类。 网站集 (由一个首要网站以及该网站下的所有网站组成,参考:http://technet.microsoft.com/zh-cn/library/cc262410.aspx )对应的类是SPSite,可以传参网站集URL给SPSite的构造方法创建对象。一般您可以这样用。 using (SPSite spSite = new SPSite("http://SharePointServer/")){ //TODO......} 有时候你可能要提升一下权限以场管理员身份执行,则可以用下面的写法——这是服务器对象模型的优势,但是如果项目选择为“部署为沙盒解决方案”则不能提升到场管理员权限。 SPSecurity.RunWithElevatedPrivileges(() => { using (SPSite spSite = new SPSite("http://SharePointServer/")) { //TODO...... }}); SharePoint里的 用户 对应的是SPUser类,也可以使用SPUserToken构造网站集对象实现模拟用户身份执行代码。 SPSecurity.RunWithElevatedPrivileges(() => { using (SPSite spSite = new SPSite("http://SharePointServer/")) { SPUser imitatedUser = spSite.RootWeb.EnsureUser(@"contoso\sanzhang"); SPUserToken token = imitatedUser.UserToken; using (SPSite siteWithUser = new SPSite("SharePointServerUrl", token)) { //TODO...... } } }); 网站 对应的类是SPWeb,SPSite有一个RootWeb属性,是网站集的根网站;SPSite还有个AllWebs属性,是它的所有网站集合(可以用索引访问),要得到SPWeb对象还可以调用SPSite对象的OpenWeb方法,传给一个URL参数(根网站的URL和网站集是相同的,所以下面的代码传空字符串,其他子网站要传标识网站的URL部分)。每个SPWeb对象也有个Webs属性,是这个网站的子网站(也可以用索引访问)。 using (SPSite spSite = new SPSite("http://SharePointServer/")){ //获取网站集根网站对象 SPWeb spRootWeb = spSite.RootWeb; Console.WriteLine("网站集的根网站是{0}", spRootWeb.Title); //用网站ID获取子网站对象 Guid webId = new Guid("{4a106421-ae78-40fd-ad62-77fecb67cf27}"); SPWeb spWeb = spSite.AllWebs[webId]; Console.WriteLine("该网站是{0}", spWeb.Title); spWeb = spRootWeb.Webs[webId]; Console.WriteLine("该网站是{0}", spWeb.Title); //用网站名称获取子网站对象 string name = "mysubweb1"; spWeb = spSite.AllWebs[name]; Console.WriteLine("该网站是{0}", spWeb.Title); spWeb = spRootWeb.Webs[name]; Console.WriteLine("该网站是{0}", spWeb.Title); //用网站URL获取子网站对象 string url = @"/mysubweb1"; spWeb = spSite.OpenWeb(url); Console.WriteLine("该网站是{0}", spWeb.Title); } 获取对网站和其他关键对象的引用请参考:http://msdn.microsoft.com/zh-cn/library/ms468609(v=office.14).aspx 。 列表 对应的类是SPList,其实SPList类对应的不仅仅是狭义的自定义列表,文档库、图片库、日历、通知、任务都可以用它来操作,还有网站资产、用户信息列表、解决方案库、列表模版库、Web部件库等等。SPWeb对象有个Lists属性,是SPListCollection类型,遍历它或者用ID、Title做索引可得到SPList对象。想了解网站中有哪些List可以用下面的代码查看: //获取网站所有列表 foreach (SPList list in spWeb.Lists) { Console.WriteLine("Title:{0} BaseType:{1} BaseTemplate:{2}", list.Title, list.BaseType, list.BaseTemplate); } //用列表标题获取列表对象 string title = @"我的客户列表"; SPList spList = spWeb.Lists[title]; Console.WriteLine("该列表是{0}。", spList.Title); //用列表ID获取列表对象 Guid id = new Guid(@"{3824b091-c7b8-409c-bcc0-7cce487d6b49}"); spList = spWeb.Lists[id]; Console.WriteLine("该列表是{0}。", spList.Title); //用列表URL获取列表对象 string listUrl = string.Format(@"{0}/{1}", spWeb.Url, "Lists/MyCustomerList/AllItems.aspx"); spList = spWeb.GetList(listUrl); Console.WriteLine("该列表是{0}。", spList.Title); 您还是否记得这些列表属性,我们在开发自定义列表时都设置过? 列表项 对应的类是SPListItem,SPList对象的Items属性是它的项目的集合,是SPListItemCollection类型的,枚举它的元素就是SPListItem对象了。不过您想访问列表项的时候一般不要直接通过SPList对象的Items属性,特别是已经存储了很多项目的大数据列表,因为可能会有不必要的数据加载影响性能。例如您想知道列表中已存在多少个项目,可以直接访问SPList对象的ItemCount属性,而不是SPList对象的Items属性的Count;如果您想得到列表中的某个项目可以调用SPList对象的GetItemById、GetItemByUniqueId等方法。 //用列表标题获取列表对象 SPList spList = spWeb.Lists["我的客户列表"]; //获取用户信息列表的项目数量 int userCount = spList.ItemCount; Console.WriteLine("我的客户列表共有{0}条项目。", userCount.ToString()); //用项目ID获取项目对象 int itemId = 18; SPListItem spListItem = spList.GetItemById(itemId); Console.WriteLine("该客户是{0}。", spListItem.Title); //用项目UniqueID获取项目对象 Guid itemUniqueId = new Guid("{83815a27-6291-416d-8db6-a77bcae4bb86}"); spListItem = spList.GetItemByUniqueId(itemUniqueId); Console.WriteLine("该客户是{0}。", spListItem.Title); 列表对象还有一个Fields的属性,是SPFieldCollection类型,遍历这个字段集合可以得到SPField对象。这就是列表的字段信息,包括字段内部名称、显示名称、类型等等。我们要访问列表项目的某个属性时就可以用SPField对象的ID,InternalName或Title。 string title = @"我的客户列表"; SPList spList = spWeb.Lists[title]; SPFieldCollection spFields = spList.Fields; //获取列表的字段信息 foreach (SPField field in spFields) { Console.WriteLine("Title:{0} InternalName:{1} TypeDisplayName:{2} TypeAsString:{3}", field.Title, field.InternalName, field.TypeDisplayName, field.TypeAsString); } Guid fieldId = new Guid("{a943ca8c-a2ad-4a90-8a78-2f6a202f6553}"); SPField spField = spFields[fieldId]; SPListItem spListItem = spList.Items[0]; //用字段的ID访问列表项目属性 Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.Id].ToString()); //用字段的InternalName访问列表项目属性 Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.InternalName].ToString()); Console.WriteLine("该用户的消费金额是{0}。", spListItem.GetFormattedValue(spField.InternalName)); //用字段的Title访问列表项目属性 Console.WriteLine("该用户的消费金额是{0}。", spListItem[spField.Title].ToString()); Console.WriteLine("该用户的消费金额是{0}。", spListItem.GetFormattedValue(spField.Title)); 您还记得开发自定义列表栏的时候我们一起设置的那些字段属性吗? SPList对象还有个GetItemByIdAllFields方法和GetItemByIdSelectedFields方法。看来我们可以按需索取项目字段了。 //用列表标题获取列表对象 string title = @"我的客户列表"; SPList spList = spWeb.Lists[title]; int itemId = 1; SPListItem spListItem = spList.GetItemByIdSelectedFields(itemId, new[] { "CustomerName", "Recency", "Frequency", "Monetary" }); //用项目的ID和字段的InternalName访问列表项目 Console.WriteLine("客户{0}的最近消费时间是{1}消费频率是{2}消费金额是{3}。", spListItem["CustomerName"].ToString(), spListItem["Recency"].ToString(), spListItem["Frequency"].ToString(), spListItem["Monetary"].ToString()); 不过,我把GetItemByIdSelectedFields方法的数组参数减掉了两个项"Frequency"和"Monetary"再运行,竟然没有看到我期待的、闪电般美丽的异常!不是说只要两个字段吗?而且随后我把SPListItem对象的Xml属性也输出时有看到了好多不是我指定索取的字段信息! string title = @"我的客户列表"; SPList spList = spWeb.Lists[title]; int itemId = 1; //删掉"Frequency"、 "Monetary" SPListItem spListItem = spList.GetItemByIdSelectedFields(itemId, new[] { "CustomerName", "Recency"}); //用项目的ID和字段的InternalName访问列表项目 Console.WriteLine("客户{0}的最近消费时间是{1}消费频率是{2}消费金额是{3}。", spListItem["CustomerName"].ToString(), spListItem["Recency"].ToString(), spListItem["Frequency"].ToString(), spListItem["Monetary"].ToString()); Console.WriteLine(@"XML:{0}",spListItem.Xml); 查看一下GetItemByIdSelectedFields方法的源代码,发现在拼接CAML查询字段时有个对SPField对象MustFetchByDefault的判断,如果这个属性是True,没有指定也会查询,而且这个SPField对象MustFetchByDefault属性是internal的。 public SPListItem GetItemByIdSelectedFields(int id, params string[] fields){ if (fields == null) { throw new ArgumentNullException("fields"); } StringBuilder builder = new StringBuilder(); foreach (string str in fields) { if (str != null) { builder.Append("<FieldRef Name=\"" + str + "\"/>"); } } foreach (SPField field in this.Fields) { bool flag = false; foreach (string str2 in fields) { if (str2 == field.InternalName) { flag = true; break; } } if (!flag && field.MustFetchByDefault) { builder.Append("<FieldRef Name=\""); builder.Append(field.InternalName); builder.Append("\"/>"); } } return this.GetItemById(id, null, false, builder.ToString());} 如何读取列表项中字段的值请参考: http://msdn.microsoft.com/zh-cn/library/ff521580(v=office.14).aspx 。 在读取项目属性时,有些类型是比较特殊的:例如多个用户或用户组,它可以转为SPFieldUserValueCollection类型,这是个SPFieldUserValue对象的集合; 用户或用户组 、超链接或图片这样的字段取出来时String类型,您要解析可以用字符串截取方式,也可以对应构造成SPFieldUserValue、SPFieldUrlValue对象,直接访问它们的属性。 SPListItem spListItem = spList.GetItemById(itemId); //直接ToString,用户是[ID]+[;#] + [显示名];链接是[URL] + [,] + [显示文本] Console.WriteLine("客户的分享者是{0} 所有者是{1} 业务系统链接是{2}。", spListItem["Sharers"], spListItem["Owner"].ToString(), spListItem["BusinessPage"].ToString()); //截取字符串取属性 Console.WriteLine("客户的所有者的显示名是{0} 业务系统链接的URL是{1}。", spListItem["Owner"].ToString().Split(new[] { @";#" }, StringSplitOptions.None)[1], spListItem["BusinessPage"].ToString().Split(‘,‘)[0]); //转为相应对象取属性 SPFieldUserValueCollection shares = (SPFieldUserValueCollection)spListItem["Sharers"]; foreach (SPFieldUserValue share in shares) { if (share.User != null) { SPUser user = share.User; Console.WriteLine(@"找到个用户{0}", user.Name); } else { SPGroup spGroup = spWeb.Groups.GetByID(share.LookupId); Console.WriteLine(@"找到个用户组{0}", spGroup.Name); } } SPFieldUserValue owner = new SPFieldUserValue(spWeb, spListItem["Owner"].ToString()); |