Search This Blog

Tuesday, July 13, 2010

SPList Management by Code




Introduction

Working with MOSS 2007 is simple and easy since you can create your own lists and manage them through SharePoint website settings. But when we start building a website under SharePoint, we need to manage and customize these lists from the code. I created a small website using Microsoft.SharePoint.dll, to manage SharePoint lists. 

Background 

My website starts by accessing a SharePoint website created locally on my computer. The first step is to access the SPSite and get the current SharePoint Website (SPWeb). After this we can start with reading all the website lists and start managing them through SPList and each list has a list of SPListItem.  

Using the code 



Using Microsoft.SharePoint namespace, we start by getting the current SPWeb. For the SPSite we need to specify the url for the SharePoint website we are using:  

Collapse
public static SPWeb GetCurrentWeb()
{
SPSite site = new SPSite("http://localhost:48/");

SPWeb myWeb = site.OpenWeb();

//to enable editing from this website
myWeb.AllowUnsafeUpdates = true;

return myWeb;
}

SPWeb myWeb = SPCalenderManagerLib.SharepointManager.GetCurrentWeb();

//fill the grid with the list of SPList
dgvLists.DataSource = myWeb.Lists;
dgvLists.DataBind();


AllUnsafeUpdates is set to true since we are modifying the website lists from outside the SharePoint.

 

As shown in the picture above, we will get all the Lists build in, or custom lists available in the current website. Now we can manage any list we need by clicking on the Edit button, or we can add a new list also from this page.

To add a new SPList, we can use the following function: 

Collapse
public static Guid CreateNewList(string listName, string listDescription, SPListTemplateType type)
{
Guid guid = Guid.Empty;
try

{
SPWeb myWeb = GetCurrentWeb();
guid = myWeb.Lists.Add(listName, listDescription, type);
}
catch { }
return guid;
}


Every list in SharePoint has its unique identifier, this function returns this as a guid that can be used for other purposes.  Every list has its Title, description and SPListTemplateType 

Now to edit an existing list, we have to check first the list of available fields in this list and to determine with fields are read only, required, editable...To get the list information, we only need to know its Title or List name using the following function: 

Collapse
public static SPList GetList(string listName)
{
SPList list = null;
try

{
SPWeb myWeb = GetCurrentWeb();
list = myWeb.Lists[listName];
}
catch { }
return list;
}

After we get the SPList, we can loop over the list Fields using the SPField list, and create a dummy table that contains the list of items that can be modified by the user (not read only fields).

Collapse
 SPList list = SPCalenderManagerLib.SharepointManager.GetList(txtListName.Text);
if (list != null)
{
dgvFields.DataSource = list.Fields;
dgvFields.DataBind();

DataTable dt = new DataTable();
foreach (SPField field in list.Fields)
{
if (field.Title == "Property Bag")
continue;

if (!field.ReadOnlyField || field.Title == "ID")
{
DataColumn col = new DataColumn();

col.ColumnName = field.Title;
col.ExtendedProperties.Add("Type", field.TypeAsString);
col.ExtendedProperties.Add("Required", field.Required);

if (!dt.Columns.Contains(col.ColumnName))
dt.Columns.Add(col);
}
}

foreach (SPListItem item in list.Items)
{
DataRow row = dt.NewRow();
foreach (SPField field in item.Fields)
{
if (field.Title == "Property Bag")
continue;

if (!field.ReadOnlyField || field.Title == "ID")
{
row[field.Title] = item[field.Title];
}
}
dt.Rows.Add(row);
}
Session["CurrentTable"] = dt;
dgv.DataSource = dt;// list.Items.GetDataTable();

dgv.DataBind();
}

This step, we need to fill up the 2 grids in the page, the first one contains the List of SPField's in the SPList we are editing, and the second one contains a custom DataTable build according to a selected fields that are not  ReadOnlyField. Or if we can use the default generated DataTable:


dgv.DataSource = list.Items.GetDataTable(); 
dgv.DataBind();



As shown in the figure above, you can see now the 2 grids. The second one includes only the editable data in every SPList.

We can also add new fields to this List:

SPList list = SPCalenderManagerLib.SharepointManager.GetList(txtListName.Text);
if (list != null)
{
int type = 0;
int.TryParse(ddlFieldTypes.SelectedValue, out type);

list.Fields.Add(txtField.Text, (SPFieldType)type, chkRequired.Checked);
list.Update();
}

For every newly added field, we need to specify the field name, SPFieldType, and whether it is required or not. list.Update() is used to add the modification to the SharePoint database. The SPFieldType is various, it can be Number, Text, another List... 

Now, in the second grid, if we click on edit or add, then we can modify the exiting data of this SPListItem: 

As you can see, the fields are automatically generated depending on the type of each field, the Text is replaced a textbox, the boolean is replaced by a Yes/No radiobuttons and the unknown types or readonly fields are replaced by labels.

 protected void dgv_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Modify")
{
int index = Convert.ToInt32(e.CommandArgument);
DataTable dt = (DataTable)Session["CurrentTable"];

DataRow row = dt.Rows[index];
List<SpecificItem> items = new List<SpecificItem>();

txtId.Value = row["ID"].ToString();

foreach (DataColumn col in dt.Columns)
{
SpecificItem item = new SpecificItem();

item.ID = int.Parse(row["ID"].ToString());
item.ItemDisplay = col.ColumnName;
item.ItemType = col.ExtendedProperties["Type"].ToString();
item.ItemValue = row[col.ColumnName];

items.Add(item);
}
Session["CurrentRow"] = items;

rptItems.DataSource = items;
rptItems.DataBind();
listItems.Visible = true;
}
else if (e.CommandName == "Remove")
{
int index = Convert.ToInt32(e.CommandArgument);
DataTable dt = (DataTable)Session["CurrentTable"];

DataRow row = dt.Rows[index];
int id = 0;
int.TryParse(row["ID"].ToString(), out id);

SPList list = SPCalenderManagerLib.SharepointManager.GetList(txtListName.Text);
if (list != null)
{
list.Items.DeleteItemById(id);

FillGrids();
}
}
}

SpecificItem is a class was created to access a custom list that will be given to the repeater in order to allow the modifications of the SPListItem easily. This class includes: 

 

public class SpecificItem
{
public int ID
{
get;
set;
}
public string ItemType
{
get;
set;
}
public string ItemDisplay
{
get;
set;
}
public object ItemValue
{
get;
set;
}
}



Now the repeater will have a datasource that includes list of  SpecificItem. For each SpecificItem, we can check the type and add the suitable control to allow the editing of the SPListItem.  


The backward step is used upon saving. We will check the SpecificItem given to the repeater and match the types with the SPListItem and then save the SPListItem 

SPList list = SPCalenderManagerLib.SharepointManager.GetList(txtListName.Text);
int id = 0;
int.TryParse(txtId.Value, out id);

List<SpecificItem> items = new List<SpecificItem>();
SPListItem item = null;
if (id > 0)
{
item = list.Items.GetItemById(id);
items = (List<SpecificItem>)Session["CurrentRow"];
}
else

{
item = list.Items.Add();
DataTable dt = (DataTable)Session["CurrentTable"];
foreach (DataColumn col in dt.Columns)
{
SpecificItem i = new SpecificItem();

i.ItemDisplay = col.ColumnName;
i.ItemType = col.ExtendedProperties["Type"].ToString();
// i.ItemValue = row[col.ColumnName];


items.Add(i);
}
}

//
foreach (SpecificItem i in items)
{
foreach (string key in Request.Form.AllKeys)
{
if (key.IndexOf("txt" + i.ItemType + "_" + i.ID + "_" + i.ItemDisplay.Replace(" ", "")) >= 0)
{
if (key.IndexOf("DateTime") >= 0)
{
DateTime date = new DateTime();
DateTime.TryParse(Request.Form[key], out date);

if (date != DateTime.MinValue)
item[i.ItemDisplay] = date;
}
else

item[i.ItemDisplay] = Request.Form[key].ToString();
break;
}

if (key.IndexOf("chk" + "_" + i.ID + "_" + i.ItemDisplay.Replace(" ", "")) >= 0)
{
item[i.ItemDisplay] = Request.Form[key] == "yes";// Convert.ToBoolean(Request.Form[key]);

break;
}

if (key.IndexOf("txt" + i.ItemType + "_" + i.ID + "_" + i.ItemDisplay.Replace(" ", "")) >= 0 && (key.IndexOf("Integer") > 0 || key.IndexOf("Number") > 0))
{
if (key.IndexOf("Integer") >= 0)
{
int val = 0;
int.TryParse(Request.Form[key].ToString(), out val);

item[i.ItemDisplay] = val;
}
else

{
double d = 0;
double.TryParse(Request.Form[key].ToString(), out d);
item[i.ItemDisplay] = d;
}
break;
}
}
}

item.SystemUpdate();

The SPListItem item is an array of fields, to modify every field, we need to get the field Title and place its value. item.SystemUpdate() will save the list item into the database.   

We can also delete the SPListItem from the list after we get the SPListItem Id, 

list.Items.DeleteItemById(id); 

In this way we have viewed, edited, deleted, fully managed any SPList without accessing the SharePoint website.  

No comments:

Post a Comment