CRM 4.0里Lookup的过滤功能是个缺憾,大多是收费的解决方案。网友韩建兴提出一个很普遍的问题:
我有一個實體ShippingMark
1.它和Account是N:1
2.它和Quote是N:N
我的需求是Quote在新增已存在的ShiningMark時,
只顯示ShippingMark.AccountId=Quote.AccountId的資料,有什麽辦法嗎?
我之前写过三篇博文,是总结性的给出LookupSingle的过滤方案,在论坛里普遍被使用:
神秘的 CRM Lookup (I)
神秘的 CRM Lookup (II)
神秘的 CRM Lookup (III)
但并没有涉及到LookupMulti的问题,而这两者有很大的不同。
其实MVP Darren、刀客都有提出过利用Plugin的Execute方法来实现过滤的方案;Stunnware也有一个收费的解决方案。
我针对网友的需求给出代码,基本思想是Plugin代码通过JScript传送的参数来实现过滤的功能,这个方法的好处是不更改任何系统文件+免费。你可以根据你的需求来更改代码。
JScript部分直接调用了CRM的内部函数,所以此定制应该被视为unsupported customization(虽然是安全的).
第一部分,Plugin内容,需要注册成 Execute message on the Pre Stage/Synchronous/Server/Parent Pipeline.
/*
* Microsoft Dynamics CRM Lookup Filter
* Plug-Ins: Execute message on the Pre Stage/Synchronous/Server/Parent Pipeline.
* Jim Wang @ Aug 2009,
http://jianwang.blogspot.com
,
http://mscrm.cn
*
*/
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.IO;
using
System.Web;
using
Microsoft.Crm.Sdk;
namespace
CRMExecuteEvent
{
public
class
CRMExecuteEvent : IPlugin
{
string
lookupId;
public
void
Execute(IPluginExecutionContext context)
{
lookupId
=
HttpContext.Current.Request.QueryString[
"
id
"
]
==
null
?
null
: HttpContext.Current.Request.QueryString[
"
id
"
].ToString();
if
(lookupId
==
null
)
return
;
try
{
if
(context.InputParameters.Contains(
"
FetchXml
"
))
{
string
beforeXml
=
(String)context.InputParameters[
"
FetchXml
"
];
if
(beforeXml.Contains(
"
<entity name=\
"
new_shippingmark\
"
>
"
)
&&
beforeXml.Contains(
"
xml-platform
"
))
{
//
Customise the FetchXml query string
string
afterXml
=
"
<fetch version='1.0' page='1' count='100' output-format='xml-platform' mapping='logical'>
"
+
"
<entity name='new_shippingmark'>
"
+
"
<attribute name='new_shippingmarkid' />
"
+
"
<attribute name='new_name' />
"
+
"
<attribute name='createdon' />
"
+
"
<order attribute='new_name' />
"
+
"
<link-entity name='quote' to='new_accountid' from='customerid'>
"
+
"
<filter type='and'>
"
+
"
<condition attribute = 'customerid' operator='eq' value='
"
+
lookupId
+
"
'/>
"
+
"
</filter>
"
+
"
</link-entity>
"
+
"
<filter type='and'>
"
+
"
<condition attribute='statecode' operator='eq' value='0' />
"
+
"
<condition attribute='new_name' operator='like' value='%' />
"
+
"
</filter>
"
+
"
</entity>
"
+
"
</fetch>
"
;
//
Replace the FetchXml query string
context.InputParameters[
"
FetchXml
"
]
=
beforeXml.Replace(beforeXml, afterXml);
}
}
}
catch
(System.Web.Services.Protocols.SoapException ex)
{
throw
new
InvalidPluginExecutionException(
"
An error occurred in the CRM plug-in.
"
, ex);
}
}
}
}
第二部分,JScript的内容,放在Quote的Onload里面,你需要修改relId
var relId = "new_new_shippingmark_quote";
var lookupId = crmForm.all.customerid;
var lookupEntityTypeCode;
var navId = document.getElementById("nav" + relId);
if (navId != null)
{
var la = navId.onclick.toString();
la = la.substring(la.indexOf("loadArea"), la.indexOf(";"));
navId.onclick = function()
{
eval(la);
var areaId = document.getElementById("area" + relId + "Frame");
if(areaId != null)
{
areaId.onreadystatechange = function()
{
if (areaId.readyState == "complete")
{
var frame = frames[window.event.srcElement.id];
var li = frame.document.getElementsByTagName("li");
for (var i = 0; i < li.length; i++)
{
var action = li[i].getAttribute("action");
if(action != null && action.indexOf(relId) > 1)
{
lookupEntityTypeCode = action.substring(action.indexOf("\(")+1, action.indexOf(","));
li[i].onclick = CustomLookup;
break;
}
}
}
}
}
}
}
function CustomLookup()
{
var lookupSrc = "/" + ORG_UNIQUE_NAME + "/_controls/lookup/lookupmulti.aspx?class=&objecttypes=" + lookupEntityTypeCode + "&browse=0";
if(lookupId != null && lookupId.DataValue != null && lookupId.DataValue[0] != null)
{
lookupSrc = lookupSrc + "&id=" + lookupId.DataValue[0].id;
}
var lookupItems = window.showModalDialog(lookupSrc, null);
if (lookupItems)
{
if ( lookupItems.items.length > 0 )
{
AssociateObjects( crmFormSubmit.crmFormSubmitObjectType.value, crmFormSubmit.crmFormSubmitId.value, lookupEntityTypeCode, lookupItems, true, null, relId); // This is the CRM internal JS funciton on \_static\_grid\action.js
}
}
}