I et tidligere indlæg omkring Sitedefinitions kiggede vi på opbygningen af webtemp.xml og onet.xml filerne, der danner grundlag for de nye custom sitedefinitions.
I dette indlæg kigger jeg mere på <modules> elementet i onet.xml filer og helt konkret på hvordan man customizerer list views.
Et eksempel på et list view i en standard Sharepoint sitedefinition ses på ”Document Workspace” skabelonen.

Selvom det ser ud som en webpart, er det faktisk ikke indsat som webparts i skabelonen, men som et view element, der bliver renderet i en ListViewWebpart.
Kigger man i onet.xml filen i modules elementet ser man følgende:
<View List="$Resources:core,shareddocuments_Folder;" BaseViewID="6" WebPartZoneID="Left" />
<View List="$Resources:core,lists_Folder;/$Resources:core,tasks_Folder;" BaseViewID="7" WebPartZoneID="Left" WebPartOrder="2" />
Attributen “BaseViewID” er den der definerer renderingen af view’et (kolonner, sortering osv.). ID’et er en henvisninger til et View der ligger i liste definitionen (schema.xml).
<View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,All_Documents;" DefaultView="TRUE" MobileView="True" MobileDefaultView="True" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/dlicon.png" Url="Forms/AllItems.aspx"><!-- _locID@DisplayName="camlidDc1" _locComment=" " -->
<GroupByHeader><HTML><![CDATA[<TBODY id="titl]]></HTML>
<GetVar Name="GroupByLevelString" /><HTML><![CDATA[" groupString="]]></HTML>
...
Hvis man åbner schema.xml filen op til Dokumentbiblioteket, finder man hurtig ud af at ikke gidder at sidder og rode med views i notepad særligt længe. Der findes værktøjer til at gøre dette meget nemmere, f.eks Sharepoint Manager, men dette hjælper ikke på problemet, at views ligger i schema.xml filen og denne må ikke ændres, da den kan blive overskrevet ved opdateringer osv.
Så hvad gør man hvis man gerne vil have en ekstra kolonne, sorteret på en anden måde eller sætte en item limit på viewet? Der er 2 svar på dette spørgsmål. Enten laver du en helt ny listedefintion og laver dine egne views som du kan henvise til i sitedefinitionen eller også efterprocesserer man en standard listedefinition.
Webparten (views renderes som ListViewWebparts) hentes ud og efterprocesseres:
using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager("Sider/default.aspx", PersonalizationScope.Shared))
{
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in manager.WebParts)
{
if (wp.Title == "Dokumenter" && wp is ListViewWebPart)
{
ViewReflector vr = new ViewReflector(wp);
vr.AddViewFields(new string[] { "DocIcon", "LinkFilenameNoMenu", "Editor", "Modified" });
vr.AddQuery("<OrderBy><FieldRef Name='Modified' Ascending='FALSE' /></OrderBy>");
vr.AddRowLimit("10", false);
vr.Update();
wp.Title = "Seneste dokumenter";
manager.SaveChanges(wp);
}
}
}
Hvor ViewReflector er følgende klasse (udsnit):
class ViewReflector
{
private System.Web.UI.WebControls.WebParts.WebPart wp;
private XmlNode node;
private SPView spView;
public ViewReflector(System.Web.UI.WebControls.WebParts.WebPart Webpart)
{
wp = Webpart;
Init();
}
private void Init()
{
System.Reflection.PropertyInfo ViewProp = wp.GetType().GetProperty("View",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
spView = ViewProp.GetValue(wp, null) as SPView;
spView.GetType().InvokeMember("EnsureFullBlownXmlDocument",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod,
null, spView, null, System.Globalization.CultureInfo.CurrentCulture);
System.Reflection.PropertyInfo NodeProp = spView.GetType().GetProperty("Node",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
node = NodeProp.GetValue(spView, null) as XmlNode;
}
public void AddViewFields(string[] viewFields)
{
XmlNode viewNode = node.SelectSingleNode("ViewFields");
if (viewNode != null)
{
viewNode.RemoveAll();
foreach(string s in viewFields)
{
viewNode.AppendChild(GetViewField(viewNode.OwnerDocument, s));
}
}
}
... (flere metoder)
public void Update()
{
spView.Update();
}
}
Som man kan se har Microsoft har ikke gjort det nemt for os at customizere views, hvis det ikke gøres gennem GUI eller schema.xml. Men hvor der er vilje, er der vej, - om det så må være den snørklede vej gennem reflection.
ViewReflector.cs (3,12 kb)