While developing custom webparts, we often come across a requirement where in we need to show items from multiple lists in a grid like interface.While SPGridView is a nice control to achieve that,it has its own limitations when it comes to out of box features of sharepoint like showing default sharepoint context menu with options like 'View Properties' ,'Edit Properties' etc.
Usually , to create a context menu using SPGridView, we need to create a 'SPMenuField' in the grid and write our own code for each of the menu items.This approach is difficult to be able to achieve out of the box menu options like 'View Properties','Edit properties' etc.
The other option is to embed the javascript that sharepoint generates for context menu in the page's html. This way, this javascript would take care of rendering the context menu for us.This is the method that I have used to render this context menu.
In order to achieve this, I created a SPGridView with 'BoundField' instead of 'SPMenufield' in the user control (.ascx) of the visual webpart:
<SharePoint:SPGridView ID="gvMyDocuments" AutoGenerateColumns="false"
runat="server" AllowSorting="true" onsorting="gvMyDocuments_Sorting"
OnRowDataBound="gvMyDocuments_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Image runat="server" ID="imgDocIcon" ImageUrl="/_layouts/images/icgen.gif"/>
<asp:Image runat="server" Visible="false" ID="imgOverlay" CssClass="ms-vb-icon-overlay" ImageUrl="/_layouts/images/icgen.gif"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText ="Name" DataField="Title" HtmlEncode="false" HtmlEncodeFormatString="false" SortExpression="Title" HeaderStyle-HorizontalAlign="Left"/>
<asp:BoundField HeaderText ="Modified" DataField="Modified" SortExpression="Modified" HeaderStyle-HorizontalAlign="Left"/>
<asp:BoundField HeaderText ="ModifiedBy" DataField="ModifiedBy" SortExpression="ModifiedBy" HeaderStyle-HorizontalAlign="Left"/>
<asp:BoundField HeaderText ="ID" DataField="ID" itemstyle-cssclass="hiddencol" HeaderStyle-CssClass="hiddencol" HeaderStyle-HorizontalAlign="Left"/>
</Columns>
<RowStyle HorizontalAlign="Left" VerticalAlign="Middle" />
</SharePoint:SPGridView>
While creating the entity collection to be bound with the grid view,I created the html and assigned it to the Title field (to be bound with the 'Name' field of the GridView).
The code for creation of this html is as follows:
objRelationships.Title = GenerateTitleHtml(strNameWoExt, objSPListItem.Url, itemCount, objSPListItem.ID, objSPListItem.ParentList, objSPListItem);
where:
objSPListItem is the current SPListItem object being populated.
strNameWoExt is the document name (without extention)
objSPListItem.Url is the url for the current list item
itemCount is a unique number being incremented everytime to maintain a unique id.
objSPListItem.ID is the id of the list item.
objSPListItem.ParentList is the parent list of the list item.
The method 'GenerateTitleHtml' creates all the html necessary for creating
the context menu :
public virtual String GenerateTitleHtml(String strTitle, String strFileUrl, Int32 itemCount, Int32 ItemID, SPList itemParentList, SPListItem currentListItem)
{
StringBuilder sbHtml = new StringBuilder();
String ctxMenuJavascriptHtml = CreateContextMenu(itemParentList, itemCount);
if (!String.IsNullOrEmpty(ctxMenuJavascriptHtml))
{
sbHtml.Append(ctxMenuJavascriptHtml);
}
String strCtxId = itemCount.ToString() + Math.Abs(itemParentList.ID.GetHashCode()).ToString().Substring(0, 3);
sbHtml.Append("<div class='ms-vb itx' onmouseover='OnItem(this)' ctxname='ctx" + strCtxId + "' id='" + ItemID + "' Field='LinkFilename' Perm='0x7fffffffffffffff' EventType=''>");
sbHtml.Append("<a onclick=\"" + GetDispEx(currentListItem, itemCount) + "\" href='/" + strFileUrl + "' onfocus='OnLink(this)'>" + strTitle + "<img height='1' border='0' width='1' alt='Use SHIFT+ENTER to open the menu (new window).' class='ms-hidden' src='/_layouts/images/blank.gif'></a>");
// sbHtml.Append(strTitle);
sbHtml.Append("</div>");
sbHtml.Append("<div class='s4-ctx' onmouseover='OnChildItem(this.parentNode); return false;'>");
sbHtml.Append("<span> </span>");
sbHtml.Append("<a onfocus='OnChildItem(this.parentNode.parentNode); return false;' onclick='PopMenuFromChevron(event); return false;' href='javascript:;' title='Open Menu'></a>");
sbHtml.Append("<span> </span>");
sbHtml.Append("</div>");
String customMenuActionsHtml = CreateCustomMenuActionsHtml(itemParentList, ItemID);
if (!String.IsNullOrEmpty(customMenuActionsHtml))
{
sbHtml.Append(customMenuActionsHtml);
}
return sbHtml.ToString();
}
public String GetDispEx(SPListItem item, Int32 ctxID)
{
String strDispEx = String.Empty;
String htmlFileType = String.Empty;
String strCtxID = ctxID.ToString() + Math.Abs(item.ParentList.ID.GetHashCode()).ToString().Substring(0, 3);
if (item["HTML_x0020_File_x0020_Type"] != null)
{
htmlFileType = item["HTML_x0020_File_x0020_Type"].ToString();
}
String strDefaultItemOpenApplication = (item.ParentList.DefaultItemOpen == DefaultItemOpen.Browser) ? "1" : "0";
String strCurrentUserID = item.Web.CurrentUser.ID.ToString();
String strFileName = "";
if (item["FileRef"] != null)
{
strFileName = item["FileRef"].ToString();
}
String strRedirectToServerFile = SPEncode.ScriptEncode(SPUtility.MapToServerFileRedirect(item.ParentList.ParentWeb, strFileName, htmlFileType));
if (!String.IsNullOrEmpty(strRedirectToServerFile))
{
strRedirectToServerFile = "1" + strRedirectToServerFile;
}
String strCheckedOutToLocal = "";
if (item["IsCheckedoutToLocal"] != null)
{
strCheckedOutToLocal = item["IsCheckedoutToLocal"].ToString();
}
String strForceCheckout = item.ParentList.ForceCheckout ? "1" : "0";
String strCheckedOutUserID = "";
if (item["CheckedOutUserId"] != null)
{
strCheckedOutUserID = item["CheckedOutUserId"].ToString().Split(new char[] { '#' })[1];
}
String strPermMask = "";
if (item["PermMask"] != null)
{
strPermMask = item["PermMask"].ToString();
}
String strSetContext = "ctx=g_ctxDict['ctx" + strCtxID + "'];";
strDispEx = String.Format("return DispEx(this,event,'TRUE','FALSE','FALSE','SharePoint.OpenDocuments.3','{0}','SharePoint.OpenDocuments','{1}','{2}','{3}','{4}','{5}','{6}','{7}')", new object[] { strDefaultItemOpenApplication, htmlFileType, strRedirectToServerFile, strCheckedOutUserID, strCurrentUserID, strForceCheckout, strCheckedOutToLocal, strPermMask });
return strSetContext + strDispEx;
}
public virtual String CreateCustomMenuActionsHtml(SPList itemParentList, Int32 ItemID)
{
StringBuilder customMenuActionsHtml = new StringBuilder();
if (!customMenuActionsDivListIDs.Contains(itemParentList.ID.ToString()))
{
customMenuActionsHtml.AppendLine("<div id='ECBItems_{" + itemParentList.ID.ToString() + "}' style='display:none' height='0' width='0'>");
foreach (SPUserCustomAction objSPUserCustomAction in itemParentList.ParentWeb.UserCustomActions)
{
customMenuActionsHtml.AppendLine("<div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Title + "</div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.ImageUrl + "</div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Url + "</div>");
customMenuActionsHtml.AppendLine("<div>0x0</div>");
if (objSPUserCustomAction.Rights == SPBasePermissions.EditListItems)
{
customMenuActionsHtml.AppendLine("<div>0x4</div>");
}
else
{
customMenuActionsHtml.AppendLine("<div>0x0</div>");
}
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.RegistrationType.ToString() + "</div>");
if (objSPUserCustomAction.RegistrationId != null)
{
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.RegistrationId + "</div>");
}
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Sequence.ToString() + "</div>");
customMenuActionsHtml.AppendLine("</div>");
}
customMenuActionsHtml.AppendLine("</div>");
customMenuActionsDivListIDs.Add(itemParentList.ID.ToString());
}
return customMenuActionsHtml.ToString();
}
private String CreateContextMenu(SPList objSPList, Int32 ctxID)
{
StringBuilder javascript = new StringBuilder();
#region variables
String strListItemTitle = String.Empty;
Int32 listBaseType = 0;
Boolean navigateForFormsPages = false;
String listTemplateID = String.Empty;
String listName = String.Empty;
String viewID = String.Empty;
String strListUrlID = String.Empty;
String strHttpPath = String.Empty;
String strHttpRoot = String.Empty;
String strImagesPath = String.Empty;
String strPortalUrl = String.Empty;
String strSendToLocationName = String.Empty;
String strSendToLocationUrl = String.Empty;
Int32 recycleBinEnabled = 0;
String strOfficialFileName = String.Empty;
String strOfficialFileNames = String.Empty;
String strWriteSecurity = String.Empty;
String strSiteTitle = String.Empty;
String strListTitle = String.Empty;
String strDisplayFormUrl = String.Empty;
String strEditFormUrl = String.Empty;
Int32 isWebEditorPreview = 0;
//Int32 ctxId = 0;
String ctxId = String.Empty;
Boolean isXslView = false;
SPUser currentUser;
Boolean enableMinorVersions = false;
Int32 verEnabled = 0;
Boolean workflowsAssociated = false;
Boolean contentTypesEnabled = false;
String strCtrlName = String.Empty;
Int32 relatedCascadeLists = 0;
String strSource = String.Empty;
String strMenuHome = String.Empty;
String strHomeURL = String.Empty;
String strHomeImageURL = String.Empty;
String strMenuMyDoc = String.Empty;
String strMyDocURL = String.Empty;
String strMyDocImageURL = String.Empty;
String strMenuAudit = String.Empty;
String strAuditURL = String.Empty;
String strAuditImageURL = String.Empty;
String strMenuRollout = String.Empty;
String strRolloutAction = String.Empty;
String strMenuVersionPIM = String.Empty;
String strVersionPIMAction = String.Empty;
String strMenuCompliance = String.Empty;
String strComplianceAction = String.Empty;
Boolean isRolloutHASub = false;
Boolean isVersionPIM = false;
Int32 itemID = 0;
#endregion
#region Current Context Variables
listBaseType = (Int32)Enum.Parse(typeof(SPBaseType), objSPList.BaseType.ToString());
navigateForFormsPages = objSPList.NavigateForFormsPages == true ? true : false;
listTemplateID = ((Int32)objSPList.BaseTemplate).ToString();
listName = "{" + objSPList.ID.ToString().ToUpper() + "}";
viewID = "{" + objSPList.DefaultView.ID.ToString().ToUpper() + "}";
//strListUrlID = "/" + Page.Server.UrlEncode(objSPList.RootFolder.Url.ToString());
strListUrlID = "/" + SPHttpUtility.UrlPathEncode(objSPList.RootFolder.Url.ToString(), true);
strHttpPath = SPContext.Current.Site.Url + "/_vti_bin/owssvr.dll?CS=65001";
strHttpRoot = SPContext.Current.Site.Url;
strImagesPath = "/_layouts/images/";
strPortalUrl = SPContext.Current.Web.PortalUrl == String.Empty ? null : SPContext.Current.Web.PortalUrl;
strSendToLocationName = objSPList.SendToLocationName;
strSendToLocationUrl = objSPList.SendToLocationUrl;
recycleBinEnabled = SPContext.Current.Web.Site.WebApplication.RecycleBinEnabled == true ? 1 : 0;
strOfficialFileName = SPContext.Current.Web.Site.WebApplication.OfficialFileName;
strOfficialFileNames = "Relationships";//added for the sake of identification in js file
strWriteSecurity = Convert.ToString(objSPList.WriteSecurity);
strSiteTitle = SPContext.Current.Web.Title;
strListTitle = objSPList.Title;
strDisplayFormUrl = SPContext.Current.Site.Url + "/_layouts/listform.aspx?PageType=4&ListId={" + (Convert.ToString(objSPList.ID).ToUpper() + "}");//objSPList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;
strEditFormUrl = SPContext.Current.Site.Url + "/_layouts/listform.aspx?PageType=6&ListId={" + (Convert.ToString(objSPList.ID).ToUpper() + "}");//objSPList.Forms[PAGETYPE.PAGE_EDITFORM].Url;
isWebEditorPreview = 0;
//ctxId = objSPList.ItemCount;
ctxId = ctxID.ToString() + Math.Abs(objSPList.ID.GetHashCode()).ToString().Substring(0,3);
isXslView = false;
currentUser = SPContext.Current.Web.CurrentUser;
enableMinorVersions = objSPList.EnableMinorVersions;
verEnabled = objSPList.EnableVersioning == true ? 1 : 0;
workflowsAssociated = objSPList.WorkflowAssociations.Count > 0 ? true : false;
contentTypesEnabled = objSPList.ContentTypesEnabled;
relatedCascadeLists = 1;
#endregion
#region Constructing javascript for context object
javascript.AppendLine("<script type='text/javascript'>");
//javascript.Append("debugger;");
javascript.AppendLine("ctx = new ContextInfo();");
javascript.AppendLine("var existingHash = '';");
javascript.AppendLine("if (window.location.href.indexOf('#') > -1)");
javascript.AppendLine("{");
javascript.AppendLine("existingHash = window.location.href.substr(window.location.href.indexOf('#'));");
javascript.AppendLine("}");
javascript.AppendLine("ctx.existingServerFilterHash = existingHash;");
javascript.AppendLine("if (ctx.existingServerFilterHash.indexOf('ServerFilter=') == 1) {");
javascript.AppendLine("ctx.existingServerFilterHash = ctx.existingServerFilterHash.replace(/-/g, '&').replace(/&&/g, '-');");
javascript.AppendLine("var serverFilterRootFolder = GetUrlKeyValue('RootFolder', true, ctx.existingServerFilterHash);");
javascript.AppendLine("var currentRootFolder = GetUrlKeyValue('RootFolder', true);");
javascript.AppendLine("if ('' == serverFilterRootFolder && '' != currentRootFolder) {");
javascript.AppendLine("ctx.existingServerFilterHash += '&RootFolder=' + currentRootFolder;");
javascript.AppendLine("}");
javascript.AppendLine("window.location.hash = '';");
javascript.AppendLine("window.location.search = '?' + ctx.existingServerFilterHash.substr('ServerFilter='.length + 1);");
javascript.AppendLine("}");
javascript.AppendLine("ctx.listBaseType = " + SPHttpUtility.NoEncode(listBaseType == null ? -1 : listBaseType) + ";");
javascript.AppendLine("var varNavigateForFormsPages='" + navigateForFormsPages + "';");
javascript.AppendLine("if(varNavigateForFormsPages=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.NavigateForFormsPages = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.NavigateForFormsPages = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.listTemplate = '" + listTemplateID + "';");
javascript.AppendLine("ctx.listName = '" + listName + "';");
javascript.AppendLine("ctx.view = '" + viewID + "';");
javascript.AppendLine("ctx.listUrlDir = '" + strListUrlID + "';");
javascript.AppendLine("ctx.HttpPath = '" + strHttpPath + "';");
javascript.AppendLine("ctx.HttpRoot = '" + strHttpRoot + "';");
javascript.AppendLine("ctx.imagesPath = '" + strImagesPath + "';");
javascript.AppendLine("ctx.PortalUrl = '" + strPortalUrl + "';");
javascript.AppendLine("ctx.SendToLocationName = '" + strSendToLocationName + "';");
javascript.AppendLine("ctx.SendToLocationUrl = '" + strSendToLocationUrl + "';");
javascript.AppendLine("ctx.RecycleBinEnabled = " + recycleBinEnabled + ";");
javascript.AppendLine("ctx.OfficialFileName = '" + strOfficialFileName + "';");
javascript.AppendLine("ctx.OfficialFileNames = '" + strOfficialFileNames + "';");
javascript.AppendLine("ctx.WriteSecurity = '" + strWriteSecurity + "';");
javascript.AppendLine("ctx.SiteTitle = '" + strSiteTitle + "';");
javascript.AppendLine("ctx.ListTitle = '" + strListTitle + "';");
javascript.AppendLine("var varIsForceCheckout= '" + objSPList.ForceCheckout + "';");
javascript.AppendLine("if(varIsForceCheckout=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isForceCheckout = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isForceCheckout = true;");
javascript.AppendLine("}");
javascript.AppendLine("if (ctx.PortalUrl == '')");
javascript.AppendLine("ctx.PortalUrl = null;");
javascript.AppendLine("ctx.displayFormUrl = '" + strDisplayFormUrl + "';");
javascript.AppendLine("ctx.editFormUrl = '" + strEditFormUrl + "';");
javascript.AppendLine("ctx.isWebEditorPreview = " + isWebEditorPreview + ";");
javascript.AppendLine("ctx.ctxId = " + SPHttpUtility.NoEncode(ctxId == null ? "-1" : ctxId.ToString()) + ";");
javascript.AppendLine("var varIsXslView= '" + isXslView + "';");
javascript.AppendLine("if(varIsXslView=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isXslView = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isXslView = true;");
javascript.AppendLine("}");
javascript.AppendLine("if (g_ViewIdToViewCounterMap['" + viewID + "'] == null)");
javascript.AppendLine("g_ViewIdToViewCounterMap['" + viewID + "'] = " + SPHttpUtility.NoEncode(ctxId == null ? "-1" : ctxId.ToString()) + ";");
javascript.AppendLine("ctx.CurrentUserId = " + SPHttpUtility.NoEncode(currentUser == null ? "-1" : currentUser.ID.ToString()) + ";");
javascript.AppendLine("var varEnableMinorVersions= '" + enableMinorVersions + "';");
javascript.AppendLine("if(varEnableMinorVersions=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.EnableMinorVersions = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.EnableMinorVersions = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.verEnabled = " + verEnabled + ";");
javascript.AppendLine("var varWorkflowsAssociated='" + workflowsAssociated + "';");
javascript.AppendLine("if(varWorkflowsAssociated=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.WorkflowsAssociated = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.WorkflowsAssociated = true;");
javascript.AppendLine("}");
javascript.AppendLine("var varContentTypesEnabled='" + contentTypesEnabled + "';");
javascript.AppendLine("if(varContentTypesEnabled=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.ContentTypesEnabled = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.ContentTypesEnabled = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.HasRelatedCascadeLists = " + relatedCascadeLists + ";");
javascript.AppendLine("ctx" + ctxId + " = ctx;");
javascript.AppendLine("g_ctxDict['ctx" + ctxId + "'] = ctx;");
javascript.AppendLine("</script>");
#endregion
return javascript.ToString();
}
{
StringBuilder sbHtml = new StringBuilder();
String ctxMenuJavascriptHtml = CreateContextMenu(itemParentList, itemCount);
if (!String.IsNullOrEmpty(ctxMenuJavascriptHtml))
{
sbHtml.Append(ctxMenuJavascriptHtml);
}
String strCtxId = itemCount.ToString() + Math.Abs(itemParentList.ID.GetHashCode()).ToString().Substring(0, 3);
sbHtml.Append("<div class='ms-vb itx' onmouseover='OnItem(this)' ctxname='ctx" + strCtxId + "' id='" + ItemID + "' Field='LinkFilename' Perm='0x7fffffffffffffff' EventType=''>");
sbHtml.Append("<a onclick=\"" + GetDispEx(currentListItem, itemCount) + "\" href='/" + strFileUrl + "' onfocus='OnLink(this)'>" + strTitle + "<img height='1' border='0' width='1' alt='Use SHIFT+ENTER to open the menu (new window).' class='ms-hidden' src='/_layouts/images/blank.gif'></a>");
// sbHtml.Append(strTitle);
sbHtml.Append("</div>");
sbHtml.Append("<div class='s4-ctx' onmouseover='OnChildItem(this.parentNode); return false;'>");
sbHtml.Append("<span> </span>");
sbHtml.Append("<a onfocus='OnChildItem(this.parentNode.parentNode); return false;' onclick='PopMenuFromChevron(event); return false;' href='javascript:;' title='Open Menu'></a>");
sbHtml.Append("<span> </span>");
sbHtml.Append("</div>");
String customMenuActionsHtml = CreateCustomMenuActionsHtml(itemParentList, ItemID);
if (!String.IsNullOrEmpty(customMenuActionsHtml))
{
sbHtml.Append(customMenuActionsHtml);
}
return sbHtml.ToString();
}
public String GetDispEx(SPListItem item, Int32 ctxID)
{
String strDispEx = String.Empty;
String htmlFileType = String.Empty;
String strCtxID = ctxID.ToString() + Math.Abs(item.ParentList.ID.GetHashCode()).ToString().Substring(0, 3);
if (item["HTML_x0020_File_x0020_Type"] != null)
{
htmlFileType = item["HTML_x0020_File_x0020_Type"].ToString();
}
String strDefaultItemOpenApplication = (item.ParentList.DefaultItemOpen == DefaultItemOpen.Browser) ? "1" : "0";
String strCurrentUserID = item.Web.CurrentUser.ID.ToString();
String strFileName = "";
if (item["FileRef"] != null)
{
strFileName = item["FileRef"].ToString();
}
String strRedirectToServerFile = SPEncode.ScriptEncode(SPUtility.MapToServerFileRedirect(item.ParentList.ParentWeb, strFileName, htmlFileType));
if (!String.IsNullOrEmpty(strRedirectToServerFile))
{
strRedirectToServerFile = "1" + strRedirectToServerFile;
}
String strCheckedOutToLocal = "";
if (item["IsCheckedoutToLocal"] != null)
{
strCheckedOutToLocal = item["IsCheckedoutToLocal"].ToString();
}
String strForceCheckout = item.ParentList.ForceCheckout ? "1" : "0";
String strCheckedOutUserID = "";
if (item["CheckedOutUserId"] != null)
{
strCheckedOutUserID = item["CheckedOutUserId"].ToString().Split(new char[] { '#' })[1];
}
String strPermMask = "";
if (item["PermMask"] != null)
{
strPermMask = item["PermMask"].ToString();
}
String strSetContext = "ctx=g_ctxDict['ctx" + strCtxID + "'];";
strDispEx = String.Format("return DispEx(this,event,'TRUE','FALSE','FALSE','SharePoint.OpenDocuments.3','{0}','SharePoint.OpenDocuments','{1}','{2}','{3}','{4}','{5}','{6}','{7}')", new object[] { strDefaultItemOpenApplication, htmlFileType, strRedirectToServerFile, strCheckedOutUserID, strCurrentUserID, strForceCheckout, strCheckedOutToLocal, strPermMask });
return strSetContext + strDispEx;
}
public virtual String CreateCustomMenuActionsHtml(SPList itemParentList, Int32 ItemID)
{
StringBuilder customMenuActionsHtml = new StringBuilder();
if (!customMenuActionsDivListIDs.Contains(itemParentList.ID.ToString()))
{
customMenuActionsHtml.AppendLine("<div id='ECBItems_{" + itemParentList.ID.ToString() + "}' style='display:none' height='0' width='0'>");
foreach (SPUserCustomAction objSPUserCustomAction in itemParentList.ParentWeb.UserCustomActions)
{
customMenuActionsHtml.AppendLine("<div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Title + "</div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.ImageUrl + "</div>");
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Url + "</div>");
customMenuActionsHtml.AppendLine("<div>0x0</div>");
if (objSPUserCustomAction.Rights == SPBasePermissions.EditListItems)
{
customMenuActionsHtml.AppendLine("<div>0x4</div>");
}
else
{
customMenuActionsHtml.AppendLine("<div>0x0</div>");
}
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.RegistrationType.ToString() + "</div>");
if (objSPUserCustomAction.RegistrationId != null)
{
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.RegistrationId + "</div>");
}
customMenuActionsHtml.AppendLine("<div>" + objSPUserCustomAction.Sequence.ToString() + "</div>");
customMenuActionsHtml.AppendLine("</div>");
}
customMenuActionsHtml.AppendLine("</div>");
customMenuActionsDivListIDs.Add(itemParentList.ID.ToString());
}
return customMenuActionsHtml.ToString();
}
private String CreateContextMenu(SPList objSPList, Int32 ctxID)
{
StringBuilder javascript = new StringBuilder();
#region variables
String strListItemTitle = String.Empty;
Int32 listBaseType = 0;
Boolean navigateForFormsPages = false;
String listTemplateID = String.Empty;
String listName = String.Empty;
String viewID = String.Empty;
String strListUrlID = String.Empty;
String strHttpPath = String.Empty;
String strHttpRoot = String.Empty;
String strImagesPath = String.Empty;
String strPortalUrl = String.Empty;
String strSendToLocationName = String.Empty;
String strSendToLocationUrl = String.Empty;
Int32 recycleBinEnabled = 0;
String strOfficialFileName = String.Empty;
String strOfficialFileNames = String.Empty;
String strWriteSecurity = String.Empty;
String strSiteTitle = String.Empty;
String strListTitle = String.Empty;
String strDisplayFormUrl = String.Empty;
String strEditFormUrl = String.Empty;
Int32 isWebEditorPreview = 0;
//Int32 ctxId = 0;
String ctxId = String.Empty;
Boolean isXslView = false;
SPUser currentUser;
Boolean enableMinorVersions = false;
Int32 verEnabled = 0;
Boolean workflowsAssociated = false;
Boolean contentTypesEnabled = false;
String strCtrlName = String.Empty;
Int32 relatedCascadeLists = 0;
String strSource = String.Empty;
String strMenuHome = String.Empty;
String strHomeURL = String.Empty;
String strHomeImageURL = String.Empty;
String strMenuMyDoc = String.Empty;
String strMyDocURL = String.Empty;
String strMyDocImageURL = String.Empty;
String strMenuAudit = String.Empty;
String strAuditURL = String.Empty;
String strAuditImageURL = String.Empty;
String strMenuRollout = String.Empty;
String strRolloutAction = String.Empty;
String strMenuVersionPIM = String.Empty;
String strVersionPIMAction = String.Empty;
String strMenuCompliance = String.Empty;
String strComplianceAction = String.Empty;
Boolean isRolloutHASub = false;
Boolean isVersionPIM = false;
Int32 itemID = 0;
#endregion
#region Current Context Variables
listBaseType = (Int32)Enum.Parse(typeof(SPBaseType), objSPList.BaseType.ToString());
navigateForFormsPages = objSPList.NavigateForFormsPages == true ? true : false;
listTemplateID = ((Int32)objSPList.BaseTemplate).ToString();
listName = "{" + objSPList.ID.ToString().ToUpper() + "}";
viewID = "{" + objSPList.DefaultView.ID.ToString().ToUpper() + "}";
//strListUrlID = "/" + Page.Server.UrlEncode(objSPList.RootFolder.Url.ToString());
strListUrlID = "/" + SPHttpUtility.UrlPathEncode(objSPList.RootFolder.Url.ToString(), true);
strHttpPath = SPContext.Current.Site.Url + "/_vti_bin/owssvr.dll?CS=65001";
strHttpRoot = SPContext.Current.Site.Url;
strImagesPath = "/_layouts/images/";
strPortalUrl = SPContext.Current.Web.PortalUrl == String.Empty ? null : SPContext.Current.Web.PortalUrl;
strSendToLocationName = objSPList.SendToLocationName;
strSendToLocationUrl = objSPList.SendToLocationUrl;
recycleBinEnabled = SPContext.Current.Web.Site.WebApplication.RecycleBinEnabled == true ? 1 : 0;
strOfficialFileName = SPContext.Current.Web.Site.WebApplication.OfficialFileName;
strOfficialFileNames = "Relationships";//added for the sake of identification in js file
strWriteSecurity = Convert.ToString(objSPList.WriteSecurity);
strSiteTitle = SPContext.Current.Web.Title;
strListTitle = objSPList.Title;
strDisplayFormUrl = SPContext.Current.Site.Url + "/_layouts/listform.aspx?PageType=4&ListId={" + (Convert.ToString(objSPList.ID).ToUpper() + "}");//objSPList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;
strEditFormUrl = SPContext.Current.Site.Url + "/_layouts/listform.aspx?PageType=6&ListId={" + (Convert.ToString(objSPList.ID).ToUpper() + "}");//objSPList.Forms[PAGETYPE.PAGE_EDITFORM].Url;
isWebEditorPreview = 0;
//ctxId = objSPList.ItemCount;
ctxId = ctxID.ToString() + Math.Abs(objSPList.ID.GetHashCode()).ToString().Substring(0,3);
isXslView = false;
currentUser = SPContext.Current.Web.CurrentUser;
enableMinorVersions = objSPList.EnableMinorVersions;
verEnabled = objSPList.EnableVersioning == true ? 1 : 0;
workflowsAssociated = objSPList.WorkflowAssociations.Count > 0 ? true : false;
contentTypesEnabled = objSPList.ContentTypesEnabled;
relatedCascadeLists = 1;
#endregion
#region Constructing javascript for context object
javascript.AppendLine("<script type='text/javascript'>");
//javascript.Append("debugger;");
javascript.AppendLine("ctx = new ContextInfo();");
javascript.AppendLine("var existingHash = '';");
javascript.AppendLine("if (window.location.href.indexOf('#') > -1)");
javascript.AppendLine("{");
javascript.AppendLine("existingHash = window.location.href.substr(window.location.href.indexOf('#'));");
javascript.AppendLine("}");
javascript.AppendLine("ctx.existingServerFilterHash = existingHash;");
javascript.AppendLine("if (ctx.existingServerFilterHash.indexOf('ServerFilter=') == 1) {");
javascript.AppendLine("ctx.existingServerFilterHash = ctx.existingServerFilterHash.replace(/-/g, '&').replace(/&&/g, '-');");
javascript.AppendLine("var serverFilterRootFolder = GetUrlKeyValue('RootFolder', true, ctx.existingServerFilterHash);");
javascript.AppendLine("var currentRootFolder = GetUrlKeyValue('RootFolder', true);");
javascript.AppendLine("if ('' == serverFilterRootFolder && '' != currentRootFolder) {");
javascript.AppendLine("ctx.existingServerFilterHash += '&RootFolder=' + currentRootFolder;");
javascript.AppendLine("}");
javascript.AppendLine("window.location.hash = '';");
javascript.AppendLine("window.location.search = '?' + ctx.existingServerFilterHash.substr('ServerFilter='.length + 1);");
javascript.AppendLine("}");
javascript.AppendLine("ctx.listBaseType = " + SPHttpUtility.NoEncode(listBaseType == null ? -1 : listBaseType) + ";");
javascript.AppendLine("var varNavigateForFormsPages='" + navigateForFormsPages + "';");
javascript.AppendLine("if(varNavigateForFormsPages=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.NavigateForFormsPages = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.NavigateForFormsPages = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.listTemplate = '" + listTemplateID + "';");
javascript.AppendLine("ctx.listName = '" + listName + "';");
javascript.AppendLine("ctx.view = '" + viewID + "';");
javascript.AppendLine("ctx.listUrlDir = '" + strListUrlID + "';");
javascript.AppendLine("ctx.HttpPath = '" + strHttpPath + "';");
javascript.AppendLine("ctx.HttpRoot = '" + strHttpRoot + "';");
javascript.AppendLine("ctx.imagesPath = '" + strImagesPath + "';");
javascript.AppendLine("ctx.PortalUrl = '" + strPortalUrl + "';");
javascript.AppendLine("ctx.SendToLocationName = '" + strSendToLocationName + "';");
javascript.AppendLine("ctx.SendToLocationUrl = '" + strSendToLocationUrl + "';");
javascript.AppendLine("ctx.RecycleBinEnabled = " + recycleBinEnabled + ";");
javascript.AppendLine("ctx.OfficialFileName = '" + strOfficialFileName + "';");
javascript.AppendLine("ctx.OfficialFileNames = '" + strOfficialFileNames + "';");
javascript.AppendLine("ctx.WriteSecurity = '" + strWriteSecurity + "';");
javascript.AppendLine("ctx.SiteTitle = '" + strSiteTitle + "';");
javascript.AppendLine("ctx.ListTitle = '" + strListTitle + "';");
javascript.AppendLine("var varIsForceCheckout= '" + objSPList.ForceCheckout + "';");
javascript.AppendLine("if(varIsForceCheckout=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isForceCheckout = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isForceCheckout = true;");
javascript.AppendLine("}");
javascript.AppendLine("if (ctx.PortalUrl == '')");
javascript.AppendLine("ctx.PortalUrl = null;");
javascript.AppendLine("ctx.displayFormUrl = '" + strDisplayFormUrl + "';");
javascript.AppendLine("ctx.editFormUrl = '" + strEditFormUrl + "';");
javascript.AppendLine("ctx.isWebEditorPreview = " + isWebEditorPreview + ";");
javascript.AppendLine("ctx.ctxId = " + SPHttpUtility.NoEncode(ctxId == null ? "-1" : ctxId.ToString()) + ";");
javascript.AppendLine("var varIsXslView= '" + isXslView + "';");
javascript.AppendLine("if(varIsXslView=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isXslView = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.isXslView = true;");
javascript.AppendLine("}");
javascript.AppendLine("if (g_ViewIdToViewCounterMap['" + viewID + "'] == null)");
javascript.AppendLine("g_ViewIdToViewCounterMap['" + viewID + "'] = " + SPHttpUtility.NoEncode(ctxId == null ? "-1" : ctxId.ToString()) + ";");
javascript.AppendLine("ctx.CurrentUserId = " + SPHttpUtility.NoEncode(currentUser == null ? "-1" : currentUser.ID.ToString()) + ";");
javascript.AppendLine("var varEnableMinorVersions= '" + enableMinorVersions + "';");
javascript.AppendLine("if(varEnableMinorVersions=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.EnableMinorVersions = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.EnableMinorVersions = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.verEnabled = " + verEnabled + ";");
javascript.AppendLine("var varWorkflowsAssociated='" + workflowsAssociated + "';");
javascript.AppendLine("if(varWorkflowsAssociated=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.WorkflowsAssociated = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.WorkflowsAssociated = true;");
javascript.AppendLine("}");
javascript.AppendLine("var varContentTypesEnabled='" + contentTypesEnabled + "';");
javascript.AppendLine("if(varContentTypesEnabled=='False')");
javascript.AppendLine("{");
javascript.AppendLine("ctx.ContentTypesEnabled = false;");
javascript.AppendLine("}");
javascript.AppendLine("else");
javascript.AppendLine("{");
javascript.AppendLine("ctx.ContentTypesEnabled = true;");
javascript.AppendLine("}");
javascript.AppendLine("ctx.HasRelatedCascadeLists = " + relatedCascadeLists + ";");
javascript.AppendLine("ctx" + ctxId + " = ctx;");
javascript.AppendLine("g_ctxDict['ctx" + ctxId + "'] = ctx;");
javascript.AppendLine("</script>");
#endregion
return javascript.ToString();
}
Hi Bhavya!
ReplyDeleteCould you give me more detail about this statement: "objRelationships.Title = GenerateTitleHtml(strNameWoExt, objSPListItem.Url, itemCount, ......)"
where the "objRelationships" came from???
Many Thanks,
Jay
Hi Jay,
ReplyDeleteobjRelationships is basically our entity class object which we are binding with the SPGridView.
The Title property in this entity class is bound with the 'Name' field in the SPGridView.
You can get the html for the context menu generated by calling the 'GenerateTitleHtml' method and can assign it to any field in you own entity class.
Thanks,
Bhavya
Hi,
ReplyDeleteI have been looking for this for a while. Was going to give up my project but you made my day!
Instead of a gridView, i have to use a treeview in my webpart. Do you think i can use your code as well on my treeview nodes?
What about customMenuActionsDivListIDs? it is not defined in the code above.
Thanks in advance
Mathieu
Hi Mathieu,
ReplyDeleteYes, you can use the same code with a treeview as well.
Please carry out the following steps:
1. Remove the SPGridview from the user control for the visual webpart (.ascx).
2. Add a treeview to the user control like this:
<asp:TreeView ID="TreeView1" runat="server">
</asp:TreeView>
3. Add the following code on 'Page_Load' in order to populate the treeview with the entity collection containing the 'Title' field.(For eg.,in this case, it is 'objRelationshipCollection').
The 'Title' field of this collection contains the HTML code generated for the context menu.
TreeNode tvRootNode = new TreeNode("Root", "Root");
foreach (ENTITES.Relationships objRelationShip in objRelationshipCollection)
{
TreeNode tvNode = new TreeNode(objRelationShip.Title, objRelationShip.Name, objRelationShip.IconImagePath);
tvRootNode.ChildNodes.Add(tvNode);
}
TreeView1.Nodes.Add(tvRootNode);
TreeView1.ShowExpandCollapse = true;
TreeView1.ShowLines = true;
This will generate the treeview with a context menu being displayed for each node.
As far as 'customMenuActionsDivListIDs' is concerned, you can declare it as a class level variable like this:
private List<String> customMenuActionsDivListIDs = new List<String>();
Thanks a lot for your time, very usefull.
ReplyDeleteI made a first attempt with a non visual webpart befor your post. Strugleed a litle bit but i started to have result.
Will try with a visual webpart as well if i have difference in the rendering of the contextual menu.
Have a nice day
Mathieu
Mathieu
Hi,
ReplyDeleteI was wondering if you could give me a link for the source code.
Thanks,
Peter
Hi Bhavya,
ReplyDeleteI am new to sharepoint.
Can you please share your complete code.
This seems to be something I had been looking for but unable to gather together.
I think I have some missing pieces.
Can you please post the entire code, not sure why when I try this code, its displaying the generated html on the page.
ReplyDeleteThis comment has been removed by the author.
DeleteHi Kanishka,
ReplyDeleteDue to confidentiality reasons,I won't be able to share the complete source code but am happy to help in resolving the issues that you are facing.
Usually ,this issue occurs due to the html encoding on the gridview field bound with the context menu html.
As stated in the code snippet above, you have to set 2 properties HtmlEncode="False" and HtmlEncodeFormatString="false"
<asp:BoundField HeaderText ="Name" DataField="Title" HtmlEncode="false" HtmlEncodeFormatString="false" SortExpression="Title" HeaderStyle-HorizontalAlign="Left"/>
Did you set these 2 properties?
Thanks,
Bhavya
Hi Bhavya!
ReplyDeleteThank you very much for posting your solution here, really nice way of creating the "standard menu" for SharePoint.
I have almost got it to work but I am struggling with getting the "edit properties" and "view properties" functions in the menu to work.
When these are pressed nothing happens and when debugging in explorer i get the following exception "Unable to retrieve the value of the property clvp: object is null or undefined" when triggering the javascript function EditItem2. This javascript function is called when the view properties is pressed.
I have your solution hooked up against a document library and everything else in your custom menu, such as view version history, workflows etc works.
If you have the time to help me I would be very happy!
Thank you!
//Johannes
Hi Bhavya,
ReplyDeleteI had used SPSiteDataQuery to fetch the documents across multiple document libraries and displayed it in a SPGridView. Now I need to enable the default context menu to it. Please guide me on how to accomplish this. Method "GenerateTitleHtml" requires parameter like SPListItem's Id, url. Can you please assist me in doing it.
Thanks in advance !
Arun
Hi Arun, I suppost we get the "ListID" property in the dataset that we get from SPSitedataquery, you can make use of that.
ReplyDeleteCan you please provide the zip file of the code, i need it really stucked with the problem like this...
ReplyDeletemy gmail id is rohit.dhiman2011@gmail.com
ReplyDeletePlease provide the zip file for the above solution.
ReplyDeleteHi ... thanks for your article. I tried your solution and it works perfectly (SPGridView with BoundField rendered in Webpart over SharePoint Server 2010).
ReplyDeleteI only have one question ... the first menu item once opened and closed the first time is not it opens more. The behavior occurs only with the first menu item, the others work perfectly but the fist open it only one time.
Have you also experienced this behavior?
Hi Pietro,
DeleteI haven't experienced this behaviour earlier but going by the description, I think it might have something to do with multiple instances of this webpart or any other list view webpart on the same page.
This might result in the javascript being emitted multiple times on the page which might cause this behaviour.
If this is the case, then please try removing all other webparts from the page and test with only 1 instance of this webpart on the page.
Thanks,
Bhavya
Hello Bhavya,
ReplyDeleteThanks for the wonderful solution
I am able to generate ECB menu for Grid and Tree view both.
It works fine in IE8 but doesn't works in the Latest versions of IE/Firefox/Chrome.
Can you suggest/help what could be wrong here....
Hi, Thanks for solution, but in my case for Version History Menu; sometime it opens in Popup and some time redirect to page.. any suggestion on this..
ReplyDeleteThanks