Sharepoint 2007 用代码聚合所有子网站文章 (populating data sources in code)
按我們說,你想從一個網站集中的任何子網站中聚集新聞文章。現在,通過用作為AggregateDataSource鏈接數據源和SharePoint Designer這將是很容易做到這一點。但是一旦子網站變化,你將不得不在SPD里重新標記數據源或是純手動地。
?
現在,有人會說,你可以使用跨站點SPDataSource做到這一點,等等,他們當然是對的。有得到的最終結果更簡單的方法,但本文的目的是為了向你展示如何修改組件運行時。如果你想作一個簡單的聚集,使用內容查詢Web部件,一個跨站點SPDataSource甚至RSS。如果你想學習組件運行時修改,繼續住下閱讀。
?
只為了確保你理解我們的立場,我將解釋AggregateDataSource以及在SPD如何創建一個鏈接的數據源。即使您知道如何做到這一點,請按照示例以便您了解我們面臨的問題時,我們有一個動態的網站結構和的理解我們正在努力地聚集的網站結構。
?
首先,我們首先假設下面的網站結構:
現在,在每一個子網站中,我們有個自定義列表名為“文章”包含至少'Title'和'Pri'列表欄。我們需要有一個Web部件聚集所有的文章的所有標題,基于"pri"字段排序。
如果網站結構是靜態的,你可以通過使用一種稱為鏈接數據源來完成。啟動SPD來創建一個,轉到數據源庫窗格。在最底部,點擊“鏈接到其他庫…”,然后,對于結構中每個子網站,單擊添加,然后輸入一個名稱和子網站的位置。
?
?
如果你再看看數據源庫,你會發現其中提供給你的數據源,你現在可以使用所有你輸入的地址的子網站的列表。你可以添加任何一個Web部件列表或數據源到頁面。但是,我們希望從數個列表里聚集所有文章,為此,我們需要一個鏈接數據源。
?
展開鏈接源節點,然后單擊“新建鏈接源...”,然后按[配置鏈接源...]。對于之前添加的每個子網站,雙擊添加文章列表到‘選擇的數據源’列表框,然后單擊[下一步]。
?
?
在接下來的頁面上,請確保您選擇'合并'選項,然后單擊完成。?如果你喜歡,請在常規選項卡,并添加一個名稱,描述和此數據源的關鍵字。?完成后,單擊確定。
一旦你創建了新數據源,你就能拖拽新數據源到一個頁面來創建一個合并后的文章的DataFormWebPart (DFWP)。你可以操作該DFWP就像你操作任何一個其他單列表數據源DFWP。設置格式,添加或刪除字段,應用布局排版,做你想做的。
?
?
這在已預定義或列表很少變化的的靜態網站結構中很有效。但是,如果您選擇添加,編輯或移除子網站包含你想要的信息匯總,你需要修改你的數據源。
?
現在,如果你觀察在SharePoint Designer在代碼視圖的Web部件,其實你將看到你所添加的實際為一個普通的DataFormWebPart 包含一個DataSourece子節點,綠色的標記,包括一個AggregateDataSource。這些標記,只是.Net 類里展現為標簽內容的很普通的標簽。我們可以很容易操縱標簽的內容,因而,使用自定義代碼的類的行為。這就是我們如何能創建一個動態的AggregateDataSource。
?
第一件事首先,我們需要一個將操縱DataFormWebPart的數據源。創建一個新的ASPX頁面,給它個名字(我的叫MyTestPage.aspx),然后拖拽你新創建的鏈接源在SPD設計視圖中。如上所述任意布局排版或做其他任何。
現在,你可能會問:如果我要編寫代碼來操作數據源,為什么不直接寫代碼來創建整個DataFormWebPart??很棒的問題,我很高興你這樣問。
?
簡短的回答是:這樣比較簡易。
?
詳細的回答是:嗯,如果你這樣做,你要么需要繼承或具有創建自定義的DataFormWebPart的能力。通過使用已經存在DFWP你可以格式化,排版和操作,使用內置的設計功能,唯一考慮的是顯示什么數據,而不是怎么樣。?設計者會愛上你這點;他們現在能極興奮(go babanas)地漂亮做事,而你可以拖你自定義的組件到頁面某處然更改要顯示的數據。良好的開發實踐使表現從數據中分離出來。
?
讓我們繼續我們的代碼怎么樣
?
從創建一個簡單的自定義組件開始。如果你之前未曾做過,我已經寫了一篇文章將引導你分步地創建自定義組件,位于http://furuknap.blogspot.com/2008/05/creating-your-own-custom-components-for.html。然而,這個例子中,不重寫RenderContents方法,而是于OnLoad方法。如果你不希望寫所有的代碼,我附帶了一個Visual Studio 2005
的解決方案“Begin”,可以在文章的未尾看到。現在就去,然后回來。我會在這里等你。
?
重載OnLoad,確保當我們加載該組件時可以訪問DFWP的數據源。OnLoad事件發生在DataBinding事件之前,因此,我們確保在OnLoad中改變數據源是正確的設置數據源的時間。這一點很重要,一旦數據綁定方法已經執行就再沒有辦法去操縱他們,一直到結果顯示出來。
?
33 protected override void OnLoad(EventArgs e)34 {
?
既然我們要操作一個現有的DataFormWebPart控件, 我們需要一些方法去識別和訪問這個控件。我們還需要一些途徑知道哪些列表需要聚集。讓我們解決這些問題通過添加一些屬性到這個控件,添加以下行到你的類:
?
代碼 17 private string m_DataFormWebPartId;18
19 ?public string DataFormWebPartId
20 {
21 get { return m_DataFormWebPartId; }
22 set { m_DataFormWebPartId = value; }
23 }
24
25 private string m_ListName;
26
27 public string ListName
28 {
29 get { return m_ListName; }
30 set { m_ListName = value; }
31 }
?
這樣做可以讓我們在設計的時候配置這個組件。公有屬性被用作asp.net 標簽的一部分,對于實例:<MyTags:DynamicAggregateDataSource DataFormWebPartId =”MyDFWPId” ListName =”Articles” runat=”server”/>
?
現在我們有一個標識DFWP和聚集的列表名稱,需要獲得訪問DFWP數據源的方式。然后我們可以開始操縱數據源。添加以下代碼到OnLoad方法:
?
35 DataFormWebPart m_dfwp = this.Page.FindControl(DataFormWebPartId) as DataFormWebPart;36
37 m_dfwp.DataSources.Clear(); // Empty datasources
38 ?
39 AggregateDataSource ads = new AggregateDataSource();
40 ?int sourceCounter = 0;
41 SPWeb web = SPContext.Current.Web;
42 StringBuilder aggregateString = new StringBuilder();
43
44 aggregateString.AppendLine("<concat name=\"data source\">"); ?
?
第35行我們獲得了DFWP的引用。第37行清除當前數據源。第39-44行創建我們需要創建的數據源的對象和變量。我將稍候解釋這些。
?
回去看DFWP標記,特別是DataSources標簽:
?
代碼 1 <DataSources>2 <SharePoint:AggregateDataSource runat="server" IsSynchronous="false" id="Articles_x0020_from_x0020_all_x0020_subsites1″>
3 <sources>
4 <SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" selectcommand="<View></View>">
5 <SelectParameters>
6 <asp:Parameter Name="ListID" DefaultValue="DD7603E8-1705-4AC4-8F9F-6BD31D6976ED"/>
7 </SelectParameters>
8 <DeleteParameters>
9 <asp:Parameter Name="ListID" DefaultValue="DD7603E8-1705-4AC4-8F9F-6BD31D6976ED"/>
10 </DeleteParameters>
11 <UpdateParameters>
12 <asp:Parameter Name="ListID" DefaultValue="DD7603E8-1705-4AC4-8F9F-6BD31D6976ED"/>
13 </UpdateParameters>
14 <InsertParameters>
15 <asp:Parameter Name="ListID" DefaultValue="DD7603E8-1705-4AC4-8F9F-6BD31D6976ED"/>
16 </InsertParameters>
17 </SharePoint:SPDataSource>
18 <SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" selectcommand="<View></View>">
19 <SelectParameters>
20 <asp:Parameter Name="ListID" DefaultValue="9189EF30-7877-4B8D-9583-E7EE3C74C84F"/>
21 <asp:Parameter Name="WebURL" DefaultValue="/ss1/"/>
?
?
等等……為節約版面余下代碼被省略
?
此標記指示數據源的作用和我們在代碼里需要怎樣去創建。首先,如第三行標記,需一個前段代碼39行創建的AggregateDataSource。這之中包含一個屬性,在第4行標記中,名稱Source。Source屬性,盡管我們只從標識中不能得知實際為什么類型,個稅包含了許多SPDataSources的集合,標記行5和行19,其中又包含了一組Select、Delete、Update和Insert參數每個對象
?
代碼 110 <aggregate>111 <concat name=”data source”>
112 <datasource name=”Articles” id=”0″ Type=”SPList”/>
113 <datasource name=”Articles2″ id=”1″ Type=”SPList”/>
114 <datasource name=”Articles3″ id=”2″ Type=”SPList”/>
115 <datasource name=”Articles4″ id=”3″ Type=”SPList”/>
116 <datasource name=”Articles5″ id=”4″ Type=”SPList”/>
117 <datasource name=”Articles6″ id=”5″ Type=”SPList”/>
118 </concat>
119 </aggregate>
120 ?</SharePoint:AggregateDataSource>
?
?
?
此外,AggregateDataSource的Sources標簽之后有一個aggregate標記包含了一些字串。
?
在AggregateDataSource類中,此屬性不,盡管它呈現,一個集合,但而是一個字符串。這是明智的用aggregate屬性作為一個集合,因此,我們就往里添加項目,但由于某些一些原因,情況并非如此。因此,我們需要為每個我們要添加的數據源使用唯一名字和id值創建這個字符串。這就是為什么我們在代碼40和42行中有int型的sourcecounter和StringBuilder?aggregateString。
?
所以我們可以開始考慮如何讓我們的組件可以建立數據源。我們有了我們的AggregateDataSource,現在我們需要添加SPDataSources到Source屬性中。
?
從我們要聚集許多子網站,使用一個遞歸函數是很有意義的,為其取名getSubWebItems。?現在,在我的實施中我會打破一些遞歸函數方面的最佳做法,但忍耐一下,我做的一個范例,您可能會希望實現自己的遞歸。
?
該函數的簽名可以是這樣的:
?
private void getSubWebItems(AggregateDataSource ads, ref int sourceCounter, StringBuilder aggregateString, SPWeb web)?
?
?
該函數將使用Web和sourceCounter對象來操作的ads和aggregateString對象。讓我們來看看:
?
代碼 57 private void getSubWebItems(AggregateDataSource ads, ref int sourceCounter, StringBuilder aggregateString, SPWeb web)58 ?58 {
59 ?try
60 {
61 SPList list = web.Lists[m_ListName];
62 SPDataSource sds = new SPDataSource();
63 Parameter p = new Parameter();
64 p.Name = "ListId";
65 p.DefaultValue = list.ID.ToString();
66 sds.SelectParameters.Add(p);
67
68 p = new Parameter();
69 p.Name = "WebURL";
70 p.DefaultValue = web.ServerRelativeUrl;
71 sds.SelectParameters.Add(p);
72
73 sds.DataSourceMode = SPDataSourceMode.List;
74 sds.UseInternalName = true;
75
76 sds.SelectCommand = "<View></View>";
77 ads.Sources.Add(sds);
78
79 aggregateString.AppendLine("<datasource name=\"" + m_ListName + sourceCounter + "\" id=\"" + sourceCounter + "\" Type=\"SPList\"/>");
80 sourceCounter++;
81
82 }
83 ?catch (Exception)
84 {
85 // Add your own error handling
86 ?}
?
?
一個好的開發人員總是會使用try - catch對嗎?是的。行59和83-86所做的,是的,你需要添加錯誤處理。
?
行61取得一個我們當前已配置的SPWeb的組件中的ListName的引用。行62創建我們要添加到ads.DataSources的SPDataSource。然后,我們開始添加參數(行63-71),以及不同于標記代碼所示,我們只添加select參數。你可能想或者需要添加其他insert, update 和delete更好,取決于你是否要DateFormWebpart可編輯。這樣,就selectparameter模板。
?
在行77我們添加SPDateSource到ads.Sources屬性之前我們完成SPDateSource的配置。
還記得看起來像是一個集合的奇怪的aggregate字符串嗎?嗯,它只是一個字符串,我們需要拼起該字符串,使用sourceCounter讓個數據源有個唯一的字符串。在69行之前,我們結束sourceCounter遞增。
?
最后,我們需要通過調用相同的函數來遞歸內部本身。我們需要改變參數來確保不是一個無限循環。我們希望所有的子網站聚集好,所以我們在當前網站所有子網站中調用這個函數:
?
代碼 88 try89 {
90 foreach (SPWeb subweb in web.Webs)
91 {
92 getSubWebItems(ads, ref sourceCounter, aggregateString, subweb);
93 subweb.Dispose();
94 }
95
96 }
97 catch (Exception)
98 {
99 // Add your own error handling
100 ? }
101 }
?
?
代碼的最后是在Onload方法里調用getSubWebItems,清除了一些東西,然后添加AggregateDataSource到DFWP控件。
?
46 getSubWebItems(ads, ref sourceCounter, aggregateString, web);47
48 aggregateString.AppendLine("</concat>");
49
50 ads.Aggregate = aggregateString.ToString();
51
52 m_dfwp.DataSources.Add(ads);
53
54
55 }
?
?
第48-50行完成看起來像aggregateString的字符串,并將其添加到ads對象。
?
哇!?就是這樣。?代碼完成。?拍拍自己的背。?現在到了更容易的一部分,讓它運行和工作用我們的DataFormWebPart。
現在是時間來部署我們的新組件,并添加到一個頁面。這已被描述過多,包括我的位于http://furuknap.blogspot.com/2008/05/creating-your-own-custom-components-for.html的博客。我將會跳過這里,且調頭回到SharePoint Designer把我們的組件進行測試。
在SPD,打開MyTestPage.aspx頁然后添加Assembly和Register如我博客文章里描述的一樣。在代碼視圖里將有智能感知。
?
通過查找之前添加的id-value完成自定義的ASP.net組件標記。并添加到你標記的DataFormWebPartId 字段里。也添加你要聚集的列表的ListName。當然還有runat="server":
?
<MyComponents:DynamicAggregateDataSource DataFormWebPartId=”g_0de093cc_8ba4_4c03_ba5a_b8b7591baf2a” ListName=”Articles” runat=”server”/>?
保存,瀏覽器中打開,看看,你子站點的文章從此聚集到了一起。
?
?
回到美麗時刻……給出DataFormWebPart到你的designer。
讓他們確保正如想要的一樣。排序、過濾,做你想做的,你將擁有無需每次添加新站點時不斷地更新鏈接源的動態數據源的所有權力。
?
要注意以下幾點:
?
這不是可擴展的代碼!這是高開銷的操作,這個組件在每次進到這個頁面的時候遍歷你整個網站集。你很可能需要實施某種緩存或限制哪些頁面可以使用這個組件。?關鍵是要展示你如何可以操縱數據源,不會給你生產代碼。
記得添加你的程序集到到您的Web.config的SafeControls配置節點,參照:http://furuknap.blogspot.com/2008/05/creating-your-own-custom-components-for.html。如果不這樣,將會出現未被允許的控件類型 "yourcomponent" 在這個頁面。
?
當你更新或重新發布你的程序集記得重起IIS。另外,保留了你的組件簽名的一份本地緩存,所此,如果你添加或修改屬性,沒有智能感知很可能是本地緩存干擾。要刪除緩存,你需要轉到【C:\Documents and Settings\[YourUserName]\Local Settings\Application Data\Microsoft\WebsiteCache】清空目錄。別擔心,你可以安全刪除件夾中的每一項,它將被重建一旦你重新打開一個站點。清除緩存之前記得關閉SPD。
?
嘿,我們到了文章結尾。如果你有問題或者只想提出意見別忘了發表評論。我已上傳了完整的Visual Studio解決方案以供您在什么問題的時候用。
?
方便您而附加的文件:
?
初始解決方案:
dynamicaggregatedatasource_begin1.zip
?
最終解決方案:
dynamicaggregatedatasource_end1.zip
轉載于:https://www.cnblogs.com/scotcn/archive/2010/11/21/populating-data-sources-in-code.html
總結
以上是生活随笔為你收集整理的Sharepoint 2007 用代码聚合所有子网站文章 (populating data sources in code)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手把手教你架构3d游戏引擎pdf_白鹭引
- 下一篇: 合并多个nc数据_气象数据处理的火箭加速