In SharePoint 2010, one of the major changes that Microsoft has brought in development is the Client Object Model which facilitates the developers to use SharePoint 2010 Client APIs and build client based applications such as Windows Application, Silverlight and JavaScript client apps. Today, I am going to show you a nice example of using Client Object Model in .NET Managed code.
For this, first of all, I have populated few tables (Product, Category) from Microsoft Northwind Database as SharePoint lists on my site. In this example, I will deal with two of those tables which are: Product and Category. These are the screenshots of the tables:
Note that, I have a Lookup Column named ‘Category’ in Product List which is coming from ‘CategoryName’ column of Category List.
After that, I have created a Windows Application in Visual Studio 2010 and designed the following UI:
You can clearly see that my intention is to get all the categories and populate them in a Combo box and Products List Box will display all the products for that particular Category and the selected Product will display Product Details inside the Product Details Grid View. I also want to enable selecting multiple products which will make my Grid View more Dynamic so that the number of products you will select from the Product List Box, the same number of Product Details information will be there in the Grid View.
To achieve my goal, I have added the following code inside my Form Load method to initialize the items of Category Combo Box:
context.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication; //Setting the Authentication Mode
FormsAuthenticationLoginInfo formLoginInfo=new FormsAuthenticationLoginInfo("morshed","mypassword"); //Providing credentials for Forms Auth
context.FormsAuthenticationLoginInfo = formLoginInfo; //Passing the credentials to Current Client Context
web = context.Web;
var list = web.Lists.GetByTitle("Category"); //Getting the 'Category' List
var query = new CamlQuery(); //Create a new CAML query
query.ViewXml = "<View>" +
"<ViewFields>" +
"<FieldRef Name='CategoryName' />" +
"<FieldRef Name='Title' />" +
"</ViewFields>" +
"</View>"; //CAML Query details
var items = list.GetItems(query); //Receiving the items from CAML query
context.Load(items); //Loading the items in Current Context
context.ExecuteQuery(); //Calling the Client.svc to send the request to SharePoint server and receive the response
var listData = new List<DictionaryEntry>(); //Creating a Dictionary Data Structure to hold the list items
foreach (var item in items)
{
var data = new DictionaryEntry(item["CategoryName"], item["Title"]); //setting every list item's column value to Key and Value.
listData.Add(data); //Adding the data inside the Dictionary Data Structure object
}
CategoryBox.DisplayMember = "Value"; //Set the Display name of Combo Box items to item["Title"]
CategoryBox.ValueMember = "Key"; //Set the Value of Combo box items to item to item["Key"]
CategoryBox.DataSource = listData; //Setting the Data Source of Combo Box
You can see from the above code that I am querying for two columns from Category List which are: CategoryName and Title. ‘CategoryName’ is the Lookup column that I need to pass to the Product List to get the related products for the selected Category.
Now, I add the following code for selected index changed method of the Combo Box:
return; //If Nothing is selected
var category = CategoryBox.SelectedValue; //Getting the Selected Value from Category Combo Box
var list = web.Lists.GetByTitle("Product"); //Getting the 'Product' list from the current site
var query = new CamlQuery();
query.ViewXml = "<View>" +
"<Query>" +
"<Where><Eq>" +
"<FieldRef Name='Category'/>" +
"<Value Type='Lookup'>" + category+"</Value>" +
"</Eq></Where>" +
"</Query>" +
"<ViewFields>" +
"<FieldRef Name='ProductID'/>" +
"<FieldRef Name='ProductName'/>" +
"</ViewFields>" +
"</View>"; //CAML Query details to get 'ProductID' and 'ProductName' for the selected Category
var items = list.GetItems(query); //Get all items from the CAML query
context.Load(items); //Loading items
context.ExecuteQuery(); //Calling Client.svc to send the request to the SharePoint server and get the response
var listData = new List<DictionaryEntry>(); //Creating a Dictionary Data Structure to hold the list items
foreach (var item in items)
{
var data = new DictionaryEntry(item["ProductID"], item["ProductName"]); //setting every list item's column value to Key and Value.
listData.Add(data); //Adding the data inside the Dictionary Data Structure object
}
ProductListBox.DisplayMember = "Value"; //Set the Display name of List Box items to item["Title"]
ProductListBox.ValueMember = "Key"; //Set the Value of List box items to item to item["Key"]
ProductListBox.DataSource = listData; ////Setting the Data Source of the List box
Note that, in Client Object Model, unlike the Server Side Object, the actual Loading of list items or data does not happen until we call ExecuteQuery() which is synchronous for .NET Managed Code.
Now, To show multiple selected items from the Products list inside the Products Grid View, I have created the following Class:
{
public string ProductID { get; set; }
public string ProductName { get; set; }
public string SupplierID { get; set; }
public string QuantityPerUnit { get; set; }
}
To show the selected Products Details in the grid view, I have added the following code block inside the Selected Index Changed method of the Products List box:
- if (ProductListBox.SelectedIndex == -1)
- return; //If Nothing is selected inside Product List box
- var product = ProductListBox.SelectedValue; //get the single selected value of Product List box
- string strInProduct = "";
- var total = ProductListBox.Items.Count; //Total Items inside Product List Box
- for(int i=0; i<total ;i++)
- {
- if(ProductListBox.SelectedItems.Contains(ProductListBox.Items[i]))
- {
- var product1 = new DictionaryEntry(); //Create a new Dictionary Data Object to hold multiple selected items
- product1=(DictionaryEntry)ProductListBox.Items[i]; //Setting each selected item with Keys and Values
- strInProduct += "<Value Type='Number'>" + product1.Key + "</Value>"; //Modifying the CAML query clause inside 'IN' to check a range of items
- }
- }
- var list = web.Lists.GetByTitle("Product"); //Calling the 'Product' list of current site
- var query = new CamlQuery();
- query.ViewXml = "<View>" +
- "<Query>" +
- "<Where><In>" +
- "<FieldRef Name='ProductID'/><Values>" +
- strInProduct +
- "</Values></In></Where>" +
- "</Query>" +
- "<ViewFields>" +
- "<FieldRef Name='ProductID'/>" +
- "<FieldRef Name='ProductName'/>" +
- "<FieldRef Name='SupplierID'/>"+
- "<FieldRef Name='QuantityPerUnit'/>"+
- "</ViewFields>" +
- "</View>"; //Selecting 'ProductID', 'ProductName', 'SupplierID' and 'QuantityPerUnit' for each Product which are IN the range of selected items
- var items = list.GetItems(query); //Getting the items from CAML query result
- context.Load(items); //Loading the items in Current Context
- context.ExecuteQuery(); //Calling the Client.svc to send request to SharePoint server and get the response
- List<Products> spProducts = new List<Products>(); //Create a List of 'Products' class type which is already defined
- foreach (ListItem item in items)
- {
- spProducts.Add(new Products
- {
- ProductID = item["ProductID"].ToString(),
- ProductName=item["ProductName"].ToString(),
- SupplierID=item["SupplierID"].ToString(),
- QuantityPerUnit=item["QuantityPerUnit"].ToString() //Setting each property of 'spProducts' list which is 'Products' class type
- });
- }
- gvProductDetails.DataSource = spProducts; //Setting the Data Source for the Grid View with 'spProducts' list
That’s basically it. I have commented about each line of code explaining the details for your understanding.
Now, I will be able to run this application from any machine as this app is using Client Object Model. As long as you use two DLLs in your application (Microsoft.SharePoint.Client & Microsoft.SharePoint.Client.Runtime), you can get the advantage of Client Object Model APIs from any application. Here is a screenshot of the application I discussed until now:
As you can see that all the Products for a particular category is showing up inside the list box and the details of those products are being shown inside the Grid View.