Friday, August 6, 2010

Set Summary view for ListViewWebPart programmatically

As you probably know there is possibility to set <Summary view> in ListViewWebPart via UI when you select “Modify Shared Web Part” on your ListViewWebPart:

image

But is it possible to do it programmatically? I saw many questions on forums how to do it but there were no solution for this problem. I investigated it and found how to set Summary view for ListViewWebPart programmatically. But what is the problem? Here is the regular procedure which you should make when add ListViewWebPart on page programmatically:

   1: SPList targetList = ...;
   2: var webpart = new ListViewWebPart();
   3: webpart.ListName = targetList.ID.ToString("B").ToUpper();
   4: webpart.ViewGuid = targetList.DefaultView.ID.ToString("B").ToUpper();
   5:  
   6: var webPartManager = ...;
   7: webPartManager.AddWebPart(announcementsWebpart, "LeftColumnZone", 0);

Problem is that Summary view is not separate view in the target list, so you can’t get reference on this view and store it’s ID into ViewGuid property of the ListViewWebPart. So there should be some internal mechanism in ListViewWebPart which set this Summary view.

First of all I found a useful post which describes how to remove toolbar from ListViewWebPart: Changing the toolbar on a SharePoint ListViewWebPart. It doesn’t provide solution for setting Summary view programmatically, but I found direction of research – ListViewToolPart class (this is internal class so there is no documentation for it). Exactly this class is responsible for showing “Selected View” and “Toolbar Type” dropdown lists in ListViewWebPart properties. I investigated its CreateChildControls() method view Reflector:

   1: protected override void CreateChildControls()
   2: {
   3:     ...
   4:     this.viewChooser = new DropDownList();
   5:     IEnumerator enumerator = list.Views.GetEnumerator();
   6: Label_0196:
   7:     if (enumerator.MoveNext())
   8:     {
   9:         SPView current = (SPView) enumerator.Current;
  10:         if ((list.ContentTypesEnabled && !current.AllowedInRootOfList) || (current.Hidden && !(selectedAspWebPart.ViewGuid == current.InternalName)))
  11:         {
  12:             goto Label_0196;
  13:         }
  14:         item = new ListItem();
  15:         item.Value = current.InternalName;
  16:         if (!(selectedAspWebPart.ViewGuid == current.InternalName))
  17:         {
  18:             item.Text = Utility.FakeHTMLEllipsis(current.Title, 0x19);
  19:         }
  20:         else
  21:         {
  22:             item.Selected = true;
  23:             item.Text = "<" + WebPartPageResource.GetString("CurrentView", new object[0]) + ">";
  24:         }
  25:         this.viewChooser.Items.Add(item);
  26:         if (this.viewChooser.Items.Count <= 0x31)
  27:         {
  28:             goto Label_0196;
  29:         }
  30:     }
  31:     ListItem item2 = new ListItem();
  32:     item2.Text = "<" + WebPartPageResource.GetString("SummaryView", new object[0]) + ">";
  33:     item2.Value = string.Empty;
  34:     this.viewChooser.Items.Add(item2);
  35:     ...
  36: }

It iterates through all views in target list and adds items in dropdown list. After that it adds <Summary view> list item:

   1: ListItem item2 = new ListItem();
   2: item2.Text = "<" + WebPartPageResource.GetString("SummaryView", new object[0]) + ">";
   3: item2.Value = string.Empty;
   4: this.viewChooser.Items.Add(item2);

And one thing attracted my attention – when it adds list items which correspond to existing list views it sets list view’s InternalName into Value property of list item:

   1: item.Value = current.InternalName;

But when it adds list item for <Summary view> it sets string.Empty to Value of item:

   1: item2.Value = string.Empty;

So I made a hypothesis that when user selects some item from UI value of this item is stored into ViewGuid property of web part (I couldn’t see what happens directly because ListViewToolPart.ApplyChanges() method is obfuscated). And I tried to set string.Empty to ViewGuid property of ListViewWebPart when add it on page programmatically:

   1: SPList targetList = ...;
   2: var webpart = new ListViewWebPart();
   3: webpart.ListName = targetList.ID.ToString("B").ToUpper();
   4: webpart.ViewGuid = string.Empty; //targetList.DefaultView.ID.ToString("B").ToUpper();
   5:  
   6: var webPartManager = ...;
   7: webPartManager.AddWebPart(announcementsWebpart, "LeftColumnZone", 0);

And it works! After that ListViewWebPart have Summary view immediately after installing it via code. Hope this trick will help you in your work.

Update 2010-09-07: there is more easy way to add ListViewWebPart into publishing page during provisioning: use <View> element (see http://msdn.microsoft.com/en-us/library/ms438074.aspx) inside <File> element into your elementManifest.xml:

   1: <File Url="default.aspx" Type="GhostableInLibrary" Level="Published">
   2:   <Property Name="Title" Value="$Resources:cmscore,IPPT_HomeWelcomePage_Title;" />
   3:   <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/CustomLayout.aspx, ~SiteCollection/_catalogs/masterpage/CustomLayout.aspx" />
   4:   <Property Name="ContentType" Value="$Resources:cmscore,contenttype_welcomepage_name;" />
   5:   <View List="Lists/MyList"
   6:         BaseViewID="0"
   7:         Name="$Resources:CustomResources,List_MyList_Title;"
   8:         WebPartZoneID="LeftColumnZone"
   9:         WebPartOrder="0" />
  10:   ...
  11: </File>

5 comments:

  1. Trying this now with SPS 2010 but setting webpart.ViewGuid = string.Empty doesn't seem to work.

    ReplyDelete
  2. Dave,
    it worked in SP 2007. Nevertheless I found more easy way to achieve result - use View element. I updated post with example above. Hope it will help

    ReplyDelete
  3. I am trying this in SPS 2010 with the following code and regardless to what I do the calendar is added to the page showing the calendar in full view not the summary view. Any ideas?
    ListViewWebPart calendarWP = new ListViewWebPart();
    SPList calendarList = site.Lists["Calendar"]; calendarWP.ListName = calendarList.ID.ToString("B").ToUpper(); calendarWP.ViewGuid = string.Empty;

    This is not a publishing page. I need to be able to do this through code (not the elements file)

    ReplyDelete
  4. Try to use SPList.GetUncustomizedViewByBaseViewId(0) . I hope it can help.
    MSDN: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.getuncustomizedviewbybaseviewid(v=office.14).aspx

    ReplyDelete
  5. Thank you! Definitely helped me out.

    ReplyDelete