Microsoft Dynamics CRM 2013 --选项集的多选
由于从Microsoft Dynamics CRM 2011到Microsoft Dynamics CRM 2013,界面的风格发生了很大的变化
故原先在2011上开发的选项集多选在2013上面已经不再适用.
一直想不明白的是,微软为啥还不支持选项集的多选呢?
折腾的一番,具体效果如下,但还有很多不满意的地方,希望有兴趣的,或者已经做过类似功能的各位,提供下宝贵的意见,不甚感激!
具体使用步骤如下:
1.创建选项集字段,文本型字段各一个
本文使用的字段名分别为:new_post(选项集),new_post_value(保存多选值的文本型字段)
2.在窗体的OnLoad事件中添加ConvertToMultiPicklist事件,详细代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | //表单加载时转化单选为多选 function ConvertToMultiPicklist(entityName, fieldSchema) { var picklistValue = $( "#" + fieldSchema + "" + "_value" + "" ).text(); //step1:通过SOAP获取picklist的value,text列表(返回类型为Object Array,格式为[100000000,测试text]) var optionSetValueList = GetOptionSet1(entityName, fieldSchema, 2052, false ); if (optionSetValueList != null && optionSetValueList.length > 0) { //step2.1:先清空原先picklist的内容(html) $( "#" + fieldSchema + "" + "_d" + "" ).html( "" ); //step2.2:开始构建多选所需的html var appendHtml = "" ; //border:1px solid #f3f1f2; appendHtml += "<div style=\"padding-top:0px;padding-left:0px;padding-bottom:20px;padding-right:20px; margin-left:15px;\">" ; appendHtml += "<ul style=\"list-style:none;\">" ; for ( var i = 0; i < optionSetValueList.length; i++) { var checkboxId = "cb_" + fieldSchema + "_" + i; appendHtml += "<li style=\"float:left;display:block;padding-left:5px;\">" ; appendHtml += "<input type=\"checkbox\" value=\"" + optionSetValueList[i][0] + "\" style=\"width:auto;\" class=\"" + fieldSchema + "\" id=\"" + checkboxId + "\" " ; //step2.3:加载已经保存的选项 if (picklistValue.indexOf(optionSetValueList[i][0] + ":" + optionSetValueList[i][1] + ";" ) > -1) { appendHtml += "checked=\"checked\"" ; } appendHtml += "/>" ; appendHtml += "<label for=\"" + checkboxId + "\">" + optionSetValueList[i][1] + "</label>" ; appendHtml += "</li>" ; } appendHtml += "</ul>" ; appendHtml += "</div>" ; //step3:用构建好的html替换原先的picklist的html $( "#" + fieldSchema + "" + "_d" + "" ).html(appendHtml); } } |
与ConvertToMultiPicklist函数相关其他函数如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | function GetOptionSet1(entitySchema, attributeSchema, languageCode, mode) { var xmlHttpRequest = RetrieveAttribute(entitySchema, attributeSchema, mode); var optionSet = []; if (xmlHttpRequest.status == 200) { //将responseText转为responseXml var xmlDoc = new ActiveXObject( "Msxml2.DOMDocument.3.0" ); xmlDoc.async = false ; xmlDoc.loadXML(xmlHttpRequest.responseText); oXml = xmlDoc; var optionMetadataNodes = oXml.selectNodes( "//c:OptionMetadata" ); for ( var i = 0; i < optionMetadataNodes.length; i++) { optionSet[i] = []; optionSet[i][0] = optionMetadataNodes[i].selectSingleNode( "c:Value" ).text; optionSet[i][1] = "" ; var localizedLabelsData = optionMetadataNodes[i].selectSingleNode( "c:Label/a:LocalizedLabels" ); for ( var j = 0; j < localizedLabelsData.childNodes.length; j++) { var localizedLabelData = localizedLabelsData.childNodes[j]; if (localizedLabelData.selectSingleNode( "a:LanguageCode" ).text == languageCode) { optionSet[i][1] = localizedLabelData.selectSingleNode( "a:Label" ).text; } } } } else { var errorMessage = ParseError(xmlHttpRequest.responseXML); alert( "获取选项集集合失败,错误信息:" + errorMessage); } return optionSet; } |
不知啥原因,在调用GetOptionSet1,获取httpXmlRequest.responseXml的时候,一直出现未明的错误..而responseText则是正常的,故上面用的是responseText,然后再把responseText转为responseXml(转换过程中用到了ActiveXObject,所以,以上方法暂时只支持IE)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | //内部函数 获取属性MetaData function RetrieveAttribute(entitySchema, attributeSchema, mode) { var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>" ; request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" ; request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">" ; request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">" ; request += "<a:KeyValuePairOfstringanyType>" ; request += "<b:key>MetadataId</b:key>" ; request += "<b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">00000000-0000-0000-0000-000000000000</b:value>" ; request += "</a:KeyValuePairOfstringanyType>" ; request += "<a:KeyValuePairOfstringanyType>" ; request += "<b:key>RetrieveAsIfPublished</b:key>" ; request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">true</b:value>" ; request += "</a:KeyValuePairOfstringanyType>" ; request += "<a:KeyValuePairOfstringanyType>" ; request += "<b:key>EntityLogicalName</b:key>" ; request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + entitySchema + "</b:value>" ; request += "</a:KeyValuePairOfstringanyType>" ; request += "<a:KeyValuePairOfstringanyType>" ; request += "<b:key>LogicalName</b:key>" ; request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + attributeSchema + "</b:value>" ; request += "</a:KeyValuePairOfstringanyType>" ; request += "</a:Parameters>" ; request += "<a:RequestId i:nil=\"true\" />" ; request += "<a:RequestName>RetrieveAttribute</a:RequestName>" ; request += "</request>" ; request += "</Execute>" ; request += "</s:Body></s:Envelope>" ; var serverUrl = this .GetServerUrl(); var xmlHttpRequest = new XMLHttpRequest(); xmlHttpRequest.open( "POST" , serverUrl + "/XRMServices/2011/Organization.svc" + "/web" , mode); xmlHttpRequest.setRequestHeader( "SOAPAction" , "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute" ); xmlHttpRequest.setRequestHeader( "Content-Type" , "text/xml; charset=utf-8" ); xmlHttpRequest.setRequestHeader( "Content-Length" , request.length); xmlHttpRequest.send(request); return xmlHttpRequest; } |
相信看到这里,聪明的你已经会有如此的疑问:不过一个小小的功能,为啥要用SOAP的方式去获取选项集的内容?
答案:
其实我也不想的.原先的代码是直接在窗体加载的时候,去获取之前定义好的new_post(选项集)的option,可在做完这个之后,发现,在IE8,IE9,Chrome下面,居然没效果?
由于我的系统是win8,故用的是IE10.所以在开发过程中一直没发现问题的所在.
琢磨了许久,发现2013在加载控件的时候,首先加载的是一个div层,当你点击div之后,才会加载选项集的select.然而,在IE8,IE9,Chrome下面,选项集的select在页面onload完之后并没有马上出现,而是在onload完之后,大概接近1分钟后,dom才会去加载选项集的selec.而IE10却没有这样的情况.
不得已的情况下,才采用上面的方式.
另外附上原先的情况代码:
1 //表单加载时转化单选为多选 2 function ConvertToMultiPicklist(fieldSchema) { 3 4 var picklist = document.getElementById(fieldSchema); 5 var picklistValue = document.getElementById(fieldSchema + "_value").innerText; 6 7 if (picklist != null && picklistValue != null) { 8 9 //step1:获取原始picklist 10 originalSelectOption = document.getElementById(fieldSchema + "_i"); 11 12 if (originalSelectOption != null && originalSelectOption != undefined) { 13 14 var checkBoxHtml = ""; 15 16 var originalChildCount = originalSelectOption.parentElement.childElementCount; 17 18 var originalSelectOptionClone = originalSelectOption; 19 20 var selectOptionWrap = document.getElementById(fieldSchema + "_d"); 21 22 //step2:移除td下的子节点 23 for (var i = 0; i < selectOptionWrap.childElementCount ; i++) { 24 selectOptionWrap.removeChild(selectOptionWrap.childNodes[0]); 25 } 26 27 28 //↓step3:开始构建多选所需的HTML标签---begin 29 var divAdd = document.createElement("div"); 30 //divAdd.style.border = "1px solid #f3f1f2"; 31 divAdd.style.paddingTop = "0px"; 32 divAdd.style.paddingRight = "20px"; 33 divAdd.style.paddingBottom = "20px"; 34 divAdd.style.paddingLeft = "0px"; 35 divAdd.style.marginLeft = "15px"; 36 37 var ulAdd = document.createElement("ul"); 38 ulAdd.style.listStyle = "none"; 39 40 for (var i = 1; i < originalSelectOptionClone.childNodes.length; i++) { 41 var checkboxId = "cb_" + fieldSchema + "_" + i; 42 43 var liAdd = document.createElement("li"); 44 liAdd.style.cssFloat = "left"; 45 liAdd.style.display = "block"; 46 liAdd.style.paddingLeft = "5px"; 47 48 var checkboxAdd = document.createElement("input"); 49 checkboxAdd.type = "checkbox"; 50 checkboxAdd.id = checkboxId; 51 checkboxAdd.value = originalSelectOptionClone[i].value; 52 checkboxAdd.style.width = "auto"; 53 checkboxAdd.className = fieldSchema; 54 55 var labelAdd = document.createElement("label"); 56 ////labelAdd.for = checkboxId;// 这样写不知为何不起效果 57 ////labelAdd.setAttribute("for", checkboxId); 58 labelAdd.innerText = originalSelectOptionClone[i].text; 59 60 if (picklistValue.indexOf(checkboxAdd.value + ":" + labelAdd.innerText+";")>-1) { 61 checkboxAdd.checked = "checked"; 62 } 63 64 liAdd.appendChild(checkboxAdd); 65 liAdd.appendChild(labelAdd); 66 ulAdd.appendChild(liAdd); 67 68 } 69 70 divAdd.appendChild(ulAdd); 71 selectOptionWrap.appendChild(divAdd); 72 //↑step3:开始构建多选所需的HTML标签---end 73 74 } 75 } 76 }
3.最后,还需要一个OnSave事件,如下
//表单保存时保存多选值 function SaveMultiPicklist(fieldSchema) { //var checkBoxList = document.getElementsByClassName(fieldSchema); //if (checkBoxList.length <= 0) return; //var saveValues = ""; //for (var i = 0; i < checkBoxList.length; i++) { // if (checkBoxList[i].checked) { // saveValues += checkBoxList[i].value + ":" + checkBoxList[i].nextSibling.innerText + ";"; // } //} //由于IE8不支持getElemenetsByClassName,故采取下面的方式 2014年1月3日 13:54:44
var saveValues = "";
$("." + fieldSchema).each(function () {
if (this.checked) {
saveValues +=this.value + ":" + this.nextSibling.innerText + ";";
}
});
Xrm.Page.getAttribute(fieldSchema + "_value").setValue(saveValues); }
其中,new_post_value字段保存的文本格式如100000000:密码修改;100000001:会员注册;100000002:活动查询
最后,由于从vs2012开始,微软已经在其web项目集成了jQuery,故,在crm2013里,可以不引用jQuery类库了.这个确实很方面.(2013里集成的jQuery版本为1.7.2,就现在的版本来说)
最最后,希望以上内容能够帮到看到此文章的各位.同时,若有更好的解决方法,希望能不吝赐教.在此谢过!
· Linux系列:如何用perf跟踪.NET程序的mmap泄露
· 日常问题排查-空闲一段时间再请求就超时
· Java虚拟机代码是如何一步一步变复杂且难以理解的?
· 领域驱动的事实与谬误 一 DDD 与 MVC
· SQL Server 2025 中的改进
· 日常问题排查-空闲一段时间再请求就超时
· C# 14 新增功能一览,你觉得实用吗?
· 揭秘 AI 工具的系统提示词「GitHub 热点速览」
· MySQL同步ES的6种方案!
· 解密AI知识库