Monday, September 28, 2009

Populate and Update SharePoint Choice Field

SPFieldChoice and SPFieldMultiChoice are two type of SharePoint Choice field. The first one is single selection and displayed as dropdown menu or the radio buttons; the latter is multiple selections and displayed as a list of check boxes. To populate the choice items in a custom webpart, we can simply go through the Choices collection in the choice field:
    // Populate Dropdown by SharePoint Choices (single selection from dropdown menu or radio buttons)
    private void PopulateSPChoiceDropDown(DropDownList dropdown, SPList list, string fieldName)
    {
        if (dropdown == null || list == null || list.ItemCount == 0)
            return;
            
        dropdown.Items.Clear();
        if (list != null && list.Fields.ContainsField(fieldName))
        {
            SPFieldChoice spChoices = list.Fields[fieldName] as SPFieldChoice;
            if (spChoices != null && spChoices.Choices != null)
            {
                for (int i = 0; i < spChoices.Choices.Count; i++)
                {
                    dropdown.Items.Add(new ListItem(spChoices.Choices[i], spChoices.Choices[i]));
                }
            }
        }
    }

    // Populate CheckBoxList by SharePoint Choices (muliple selction)
    private void PopulateSPChoiceCheckBoxList(CheckBoxList checkboxList, SPList list, string fieldName)
    {
        if (checkboxList == null || list == null || list.ItemCount == 0)
            return;
            
        checkboxList.Items.Clear();
        if (list != null && list.Fields.ContainsField(fieldName))
        {
            SPFieldMultiChoice spChoices = list.Fields[fieldName] as SPFieldMultiChoice;
            if (spChoices != null && spChoices.Choices != null)
            {
                for (int i = 0; i < spChoices.Choices.Count; i++)
                {
                    checkboxList.Items.Add(new ListItem(spChoices.Choices[i], spChoices.Choices[i]));
                }
            }
        }
    }
As a matter of fact, we can merge above two methods into one:
    // Populate List Control such as Dropdown and CheckBoxList by SharePoint Choices
    private void PopulateSPChoiceToListControl(ListControl listControl, SPList list, string fieldName)
    {
        if (listControl == null || list == null || list.ItemCount == 0)
            return;
      
        listControl.Items.Clear();
        if (list != null && list.Fields.ContainsField(fieldName))
        {
            SPFieldMultiChoice spChoices = list.Fields[fieldName] as SPFieldMultiChoice;
            if (spChoices != null && spChoices.Choices != null)
            {
                for (int i = 0; i < spChoices.Choices.Count; i++)
                {
                    listControl.Items.Add(new ListItem(spChoices.Choices[i], spChoices.Choices[i]));
                }
            }
        }
    }
The reason we can merge them together is because SPFieldChoice is inherited from SPFieldMultiChoice, and both DropDownList and CheckBoxList are implementation of abstract ListControl class. To update the SPField:
        SPFieldMultiChoiceValue values = new SPFieldMultiChoiceValue();
        foreach (ListItem listItem in checkList.Items)
        {
            if (listItem.Selected)
            {
                values.Add(listItem.Value);
            }
        }
        item["MultipleChoiceField"] = values;
        item["SingleChoiceField"] = dropdown.SelectedValue;
        item.Update();

Tuesday, September 15, 2009

SharePoint Batch Delete

It would be inefficient to delete many List items one by one when the List is huge. SharePoint provides a batch update mechanism using CAML. Following code snippet illustrates such usage where all records in a SharePoint List that have not been updated for more than 1 year will be deleted:
    void DeleteOldListItems(SPSite site, string webUrl, string listName)
    {
        StringBuilder sbDelete = new StringBuilder();
        sbDelete.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Batch>");
        // CAML query for batch deleting
        string batchDeleteCaml = 
"<Method><SetList Scope=\"Request\">{0}</SetList><SetVar Name=\"ID\">{1}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar></Method>"; // Query items not touched for more than a year; same as <Value Type="DateTime"><Today OffsetDays="-365" /></Value> string filterQueryCaml = @"<Where><Geq><FieldRef Name='Modified'/><Value Type='DateTime' IncludeTimeValue='TRUE'>" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now.AddYears(-1)) + "</Value></Geq></Where>"; using (SPWeb web = site.OpenWeb(webUrl)) { SPList list = web.Lists[listName]; SPQuery filterQuery = new SPQuery(); filterQuery.Query = filterQueryCaml; SPListItemCollection filterItems = list.GetItems(filterQuery); foreach (SPListItem item in filterItems) { sbDelete.Append(string.Format(batchDeleteCaml, list.ID.ToString(), item.ID.ToString())); } sbDelete.Append("</Batch>"); web.ProcessBatchData(sbDelete.ToString()); } }

Thursday, September 10, 2009

SharePoint SPList.ItemCount vs SPList.Items.Count

You can get item counts of a SharePoint list by SPList.ItemCount or SPList.Items.Count property. But these two numbers can be different. The inconsistency is due to the SharePoint content security. SPList.ItemCount shows the exact item number, but SPList.Items only returns the list items that current user has access to them.

For example, if a list has 10 items, and only 5 of 10 are accessible to you, then SPList.ItemCount = 10 and SPList.Items.Count = 5 in your security context.

In addition, SPList.ItemCount is more efficient than SPList.Items.Count, because SPList.ItemCount is just a property of the list, but SPList.Items.Count will result in loading all list items (with permissions) into memory.