Advertisement

  • How to Change the Default ViewStyle of Calendar View in a SharePoint List

    I don't know about you but I find it sometimes rather upsetting when I'm looking to solve a dev task, pick up all possible resources on the subject, only to find out that some of the so much acclaimed resources don't really offer any solution. This, unfortunately, is true nearly all the time when it comes to developing SharePoint solutions and referring to Microsoft's MSDN library or books.

    Ok, let's cut through the chase, I was trying to update the default view style of a list's calendar view created via OM. I created the view using the SPView class and setting it's type property to Calendar. Then I got a collection of the SPCalendarViewStyle objects of the calendar view using the SPCalendarViewStyleCollection. Now all I needed to do was to find the right viewStyle I'd like to set as default and simply set it's properties; you would thought that would work. well I'm afraid that didn't turn out as expected!

    Below is the piece of code I'd written for this (note: this piece of code does NOT solve the problem!):


    private static void SetCalendarViewStyle(string siteUrl,
    string listName, string viewName, string newViewStyle)
    {
    using (SPSite site = new SPSite(siteUrl)){
    using (SPWeb web = site.OpenWeb("/")){
    try{
    SPList list = web.Lists[listName];
    if (list != null){
    SPView view = list.Views[viewName];
    if (view != null){
    bool styleChanged = false;
    SPCalendarViewStyleCollection coll = new SPCalendarViewStyleCollection(web, view);
    Console.WriteLine("Before View Style: {0}", coll.DefaultViewStyle.Type);
    SPSecurity.RunWithElevatedPrivileges(delegate(){
    foreach (SPCalendarViewStyle viewStyle in coll){
    if (viewStyle.Type.ToLower() == newViewStyle.ToLower()){
    // set the new default view style
    viewStyle.Default = true;
    styleChanged = true;
    }
    else{
    // set the default property of all other view style to false
    viewStyle.Default = false;
    }
    }
    if (styleChanged){
    view.Update();
    list.Update();
    Console.WriteLine("default view style changed");
    Console.WriteLine("After View Style: {0}", coll.DefaultViewStyle.Type);
    }
    });
    }
    }
    }
    catch (Exception ex) { throw ex; }
    }
    }
    }

    The list and it's calendar view referred to here were both created using OM and the list isn't listed in the quick launch. I've read a few articles and comments that suggested appending text to the end of the Url property of the view object appeared to address the problem; unfortunately that was not the case for me. Besides, the Url property of the view object is read only and I'd rather not append any text to the value of the Url property.

    To address the issue, I had to use reflection, this gave me a read/write access to the supposedly protected Node property. Then I made changes to the value of the property and simply updated the view object and its associated SPLimitedWebPartManager object.

    This piece of code solve the problem and the approach can be applied to existing calendar views.


    private static void SetCalendarViewStyle(SPWeb web,
    SPView view, DefaultCalendarView defaultView){
    SPLimitedWebPartManager vm =
    web.GetFile(view.Url).GetLimitedWebPartManager(PersonalizationScope.Shared);
    ListViewWebPart lv = null;
    foreach (System.Web.UI.WebControls.WebParts.WebPart part in vm.WebParts){
    if (part.GetType().ToString().ToLower() == "microsoft.sharepoint.webpartpages.listviewwebpart"){
    lv = part as ListViewWebPart;
    break;
    }
    }
    if (lv != null){
    PropertyInfo ViewProp = lv.GetType().GetProperty("View",
    BindingFlags.NonPublic | BindingFlags.Instance);
    SPView spView = ViewProp.GetValue(lv, null) as SPView;

    PropertyInfo viewProp = spView.GetType().GetProperty(
    "SchemaXml", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
    string root = viewProp.GetValue(spView, null) as string;
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(root);
    XmlNode node = doc.SelectSingleNode("/View/CalendarViewStyles");
    if (node == null){
    XmlNode stylesNodes = doc.CreateElement("CalendarViewStyles");
    stylesNodes.InnerXml = SetViewStyleNode(defaultView);
    doc.DocumentElement.AppendChild(stylesNodes);
    }
    else{
    node.InnerXml = SetViewStyleNode(defaultView);
    }
    PropertyInfo NodeProp = spView.GetType().GetProperty(
    "Node", BindingFlags.NonPublic | BindingFlags.Instance);
    XmlNode newNode = NodeProp.GetValue(spView, null) as XmlNode;
    newNode.InnerXml = doc.DocumentElement.InnerXml;
    spView.Update();
    vm.SaveChanges(lv);
    }
    }

4 comments:

  1. Michael S says:

    You are my hero. Thanks a lot for your code.

  1. Javier says:

    Raphael what is this method:
    SetViewStyleNode?
    You didn't include this mehtod in the code

  1. Dave says:

    Do you have code for SetViewStyleNode?

  1. You just made something that I thought was so difficult be, truly, so easy! Thanks for the post!