Showing posts with label SPList. Show all posts
Showing posts with label SPList. Show all posts

Wednesday, February 25, 2009

Dynamically creat a SPView with checkbox that will be display in a dynamically created ListViewe

Hi,

My problem was this one :

"I need to display on a specific page the default view of a list, BUT beside each items of this list must be displayed a checkbox in order to be able to select items on this list"
huuu....
The solution I chose was to recreate a clone of the defaultview that will never be displayed to the users but that will be selected as SPView of the ListView I create on my page.
Here we go...

1/ My Page takes in parameter the ID of the list I'm working on, i call the parameter "List":
Guid ListId = new Guid(this.Page.Request["List"]);
2/ Then whenever I reach the page, i check whether the view already exists, if not i create it cloning the default view and adding to it a checbox field. If the clone of the actual defaultview exists i just use it! Easy! In my code below, the listview object is called Select_List




bool creatingView = false;
SPView newView = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite Mysite = new SPSite(siteID))
{
SPWeb MyWeb = Mysite.OpenWeb(webID);
MyWeb.AllowUnsafeUpdates = true;
SPList MyList = MyWeb.Lists[ListId];
foreach (SPView view in MyList.Views)
{
if (view.Title.Equals(MyList.DefaultView.Title+ "_CloneForSelect"))
{
newView = view;
}
}
if (newView == null)
{
if (!MyList.Fields.ContainsField("Select"))
{
MyList.Fields.AddFieldAsXml("<Field Type=\"Computed\" ReadOnly=\"TRUE\" Name=\"ListItemSelection\" DisplayName=\"Select\" Sortable=\"FALSE\" Filterable=\"FALSE\" EnableLookup=\"FALSE\" SourceID=\"http://schemas.microsoft.com/sharepoint/v3\" StaticName=\"ListItemSelection\">" +"<FieldRefs> <FieldRef Name=\"ID\" /> </FieldRefs>" + "<DisplayPattern> <HTML><![CDATA[<input id=\"chk_select]]></HTML><Column Name=\"ID\" HTMLEncode=\"TRUE\" /><HTML><![CDATA[\" name=\"chk_select\" type=\"checkbox\" ]]></HTML>" + "<HTML><![CDATA[LItemId=\"]]></HTML>" + "<Column Name=\"ID\" HTMLEncode=\"TRUE\" />" + "<HTML><![CDATA[\"/> ]]></HTML>" + "</DisplayPattern></Field>");
}
SPFieldComputed fieldComp = (SPFieldComputed)MyList.Fields["Select"];
newView = MyList.DefaultView.Clone(MyList.DefaultView.Title + "_CloneForSelect", 1000, true, false);
newView.Hidden = true;
newView.Scope = SPViewScope.FilesOnly;
newView.ViewFields.Add(fieldComp);
newView.Update();
creatingView = true;
}
MyWeb.Dispose();
}
});
if (!creatingView)
{
Select_List.ViewId = newView.ID.ToString();
}
else
{
Response.Write("");
}
Select_List.ListId = this.Page.Request["List"];
Now, let me explain the code a little bit.

1/ How to create a column Checkbox in a list?

It's quite tricky cause you must create the column using a CAML definition.


 if (!MyList.Fields.ContainsField("Select"))
{
MyList.Fields.AddFieldAsXml("<Field Type=\"Computed\" ReadOnly=\"TRUE\" Name=\"ListItemSelection\" DisplayName=\"Select\" Sortable=\"FALSE\" Filterable=\"FALSE\" EnableLookup=\"FALSE\" SourceID=\"http://schemas.microsoft.com/sharepoint/v3\" StaticName=\"ListItemSelection\">" +"<FieldRefs> <FieldRef Name=\"ID\" /> </FieldRefs>" +
"<DisplayPattern> <HTML><![CDATA[<input id=\"chk_select]]></HTML><Column Name=\"ID\" HTMLEncode=\"TRUE\" /><HTML><![CDATA[\"
name=\"chk_select\" type=\"checkbox\" ]]></HTML>"
+
"<HTML><![CDATA[LItemId=\"]]></HTML>" +
"<Column Name=\"ID\" HTMLEncode=\"TRUE\" />" +
"<HTML><![CDATA[\"/> ]]></HTML>" + "</DisplayPattern></Field>");
}
Sorry for the "+" but it's for my code lisibility! In fact you just create a field where the display is an HTML input component !!
2/ OK, but now, i have the display How do I get my checkboxes values after postback ?
Well, let's continue to be tricky!! I just create two Hidden field on my page

<asp:HiddenField runat="server" id="listSrv_items" />
<asp:HiddenField runat="server" id="checked_ids" />
And on my validation button i fill it before validation using a JS function called fill_ids


<asp:Button ID="Btn_valid" OnClientClick="fill_ids();" OnClick="Btn_valid_Click" runat="server"/>
The js function simply puts inside the listSrv_Items the ids of each item in the list, and checked_ids will finally contain the list of items ids that are checked.

here we go for the js that i manually add to the page in the render method:


protected override void Render(HtmlTextWriter writer)
{
this.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript", @"
<script>
function fill_ids()
{
var items= document.getElementById('"
+ listSrv_items.ClientID + @"').value;
var checkedIds= document.getElementById('"
+ checked_ids.ClientID + @"');
checkedIds.value='';
var SParray = items.split(';');
for (ix=0; ix< SParray.length-1; ix++)
{
var item = document.getElementById("
"chk_select""+SParray[ix])
if (item!=null && item.checked)
{
checkedIds.value += SParray[ix] + ';';
}
}
if (checkedIds.value.length>0)
checkedIds.value = checkedIds.value.substr(0,checkedIds.value.length-1);
}
</script>"
);
listSrv_items.Value = "";
foreach (SPListItem item in _rootList.Items)
{
listSrv_items.Value += item.ID + ";";
}
}
Now my field checked_Ids will contain the ids of my checked items so in my Btn_valid_Click; i just have to use it to do anything I want! That's it!

Get SPList.ID From URL

I often face a problem : I have an URL, and I would like to get the list pointed by this URL. So I wanted a function that could return me this ID whenever I was passing an URL to it!

Some Regexp, some recursivity and here we are :



public SPList getListFromUrl(string url)
{
try
{
if (!url.EndsWith("/")) url = url + "/";
//match list
Regex listExpReg = new Regex("(?.+)\\/Sites\\/(?.+)\\/Lists\\/(?.+)\\/.*", RegexOptions.IgnoreCase);
if (listExpReg.IsMatch(url))
{
Match siteMatch = listExpReg.Match(url);
String racine = siteMatch.Groups["Racine"].Value;
String siteToFind = siteMatch.Groups["Sites"].Value;
String listeToFind = siteMatch.Groups["LName"].Value;
String[] splitedSiteList = siteToFind.Split('/');
SPSite rootsite = new SPSite(racine + "/Sites/" + splitedSiteList[0]);
if (rootsite != null)
{
using (SPWeb webNavigated = rootsite.RootWeb)
{
foreach (string s in splitedSiteList)
{
if (s != splitedSiteList[0])
{
SPWeb TempWeb = webNavigated.Webs[s];
webNavigated = TempWeb;
TempWeb.Dispose();
}
}
SPList listsearched = webNavigated.GetList(url);
_destinationWeb = webNavigated;
rootsite.Dispose();
}
return listsearched;
}
else
{
return null;
}
}
else
return null;
}
catch (Exception exc)
{
//BUUUUUUUUP
}
}
The function basically return null if the URL passed is not a list URL, and return the list ID whenever you pass an URL to it. It also works when you pass the url containing some allitems.aspx after the name of the list...
Try it!
Hope it helps