Dynamics CRM命令栏定制基础知识及手动编辑customization.xml实例
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复166或者20151028可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me!
前面的博文:Dynamics CRM 客户端程序开发:在实体的列表界面添加按钮 和 Dynamics CRM 客户端程序开发:自定义系统标准按钮的可用性 ,都是使用的工具Ribbon Workbench。其实SDK中介绍的方法是直接更改文件 customization.xml 的方法,算是比较原始的方法,利用工具来定制的话其实也是更改这个文件,使用Ribbon Workbench 有一个很让人吐槽的弊端就是发布较慢耗时较长,容易导致CRM出现 SQL Server Error. SQL Server timeout expired 错误。我看也要掌握比较原始的方法比较靠谱,这篇文章就是带你玩转命令栏的基本定制。
我们知道在Dynamics CRM 2011时候还没有命令栏(command bar)一说,使用的是Ribbon功能区,自从Dynamics CRM 2013以后才逐渐的由命令栏占据了主流。虽然这样,但是他们使用的xml是一样的,只是显示形式不一样,按照官方的说法,命令栏显示更为高效。因为这个xml文件最初是为Ribbon功能区设计的,所以还是称之为Ribbon定义文件。
首先要明白的是你的所有修改都要放在 customization.xml 这个文件中 RibbonDiffXml 这个元素下面的 CustomAction 元素或者 HideCustomAction 元素中。要定制Ribbon,需要对现有Ribbon的定义有所了解,比较直接的方法是导出来看看,这是这篇博文带领大家做的第一件事情。当然啦,也可以直接查看未经客制化的accountRibbon.xml定义文件,这些文件在 SDK\Resources\ExportedRibbonXml 文件夹中,比如客户实体的命令栏定义文件是 accountRibbon.xml 。说到这些Ribbon定义文件,有一个重要的Ribbon定义文件,大家可能猜到了,那就是一个作为模板的Ribbon定义文件:applicationRibbon.xml 。导出Ribbon定义文件主要涉及到两个消息,其中的一个 RetrieveApplicationRibbonRequest 便是导出这个模板 applicationRibbon.xml 文件的。我使用如下的代码来导出它,导出来行数还挺多,7812行。
static void Main(string[] args) { var service = GetOrganizationService(); RetrieveApplicationRibbonRequest appribReq = new RetrieveApplicationRibbonRequest(); RetrieveApplicationRibbonResponse appribResp = (RetrieveApplicationRibbonResponse)service.Execute(appribReq); File.WriteAllBytes(@"D:\luoyong\applicationRibbon.xml", unzipRibbon(appribResp.CompressedApplicationRibbonXml)); Console.WriteLine("程序运行完成!"); Console.ReadKey(); } /// <summary> /// A helper method that decompresses the the Ribbon data returned /// </summary> /// <param name="data">The compressed ribbon data</param> /// <returns></returns> static byte[] unzipRibbon(byte[] data) { System.IO.Packaging.ZipPackage package = null; MemoryStream memStream = null; memStream = new MemoryStream(); memStream.Write(data, 0, data.Length); package = (ZipPackage)ZipPackage.Open(memStream, FileMode.Open); ZipPackagePart part = (ZipPackagePart)package.GetPart(new Uri("/RibbonXml.xml", UriKind.Relative)); using (Stream strm = part.GetStream()) { long len = strm.Length; byte[] buff = new byte[len]; strm.Read(buff, 0, (int)len); return buff; } }
我使用如下的代码导出某个实体的Ribbon定义文件,我这里导出逻辑名称为 new_test 的Ribbon定义,导出来行数还挺多,5027行。
static void Main(string[] args) { var service = GetOrganizationService(); const string entityName = "new_test"; RetrieveEntityRibbonRequest entRibReq = new RetrieveEntityRibbonRequest() { RibbonLocationFilter = RibbonLocationFilters.All }; entRibReq.EntityName = entityName; RetrieveEntityRibbonResponse entRibResp = (RetrieveEntityRibbonResponse)service.Execute(entRibReq); System.String entityRibbonPath = Path.GetFullPath(@"D:\luoyong\" + entityName + "Ribbon.xml"); File.WriteAllBytes(entityRibbonPath, unzipRibbon(entRibResp.CompressedEntityXml)); Console.WriteLine("程序运行完成!"); Console.ReadKey(); }
按钮我们主要是能在三个地方用到看到,第一个就是实体的列表界面的命令栏,第二个打开显示一条记录的表单界面,第三个就是子网格也会有个命令栏。下面列举了会应用到每个实体命令栏的Tab:
Tab命名形式 | 显示区域 | 备注 |
Mscrm.Form.{!实体逻辑名称}.MainTab | 实体表单界面 | 以Mscrm.Form.开头 |
Mscrm.Form.{!实体逻辑名称}.Related | ||
Mscrm.Form.{!实体逻辑名称}.Developer | ||
Mscrm.HomepageGrid.{!实体逻辑名称}.MainTab | 实体列表界面 | 以Mscrm.HomepageGrid开头 |
Mscrm.HomepageGrid.{!实体逻辑名称}.View | ||
Mscrm.HomepageGrid.{!实体逻辑名称}.Related | ||
Mscrm.HomepageGrid.{!实体逻辑名称}.Developer | ||
Mscrm.SubGrid.{!实体逻辑名称}.ContextualTabs | 子网格界面 | 以Mscrm.SubGrid 开头。但是Dynamics CRM 2013版本以后只有三个按钮,一个新增,一个列表,一个删除。你不能增加显示更多按钮,但是可以隐藏一些按钮。也可以定制点击这些按钮的时候执行的操作。 |
Mscrm.SubGrid.{!实体逻辑名称}.MainTab |
你可能会问后面这些MainTab,Related,Developer,View 等等分别代表什么含义,我截个Dynamics CRM 2011的图你就知道了,以前的Ribbon功能区是分很多Tab的。Dynamics CRM 2013以后的版本不分了。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610215843302-610928336.jpg)
下面我们来尝试来增加一个命令栏按钮看看。首先需要一个解决方案,我这里已经新建好了一个名称为 RibbonSolution的解决方案,然后进添加你要修改的实体(添加现有 > 实体),当弹出窗口缺少必须组件的时候,我们选择 否,不包含必须组件 就可以。因为我们只是自定义Ribbon区所以那些组件可以不添加。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610215916295-1882558380.jpg)
然后我们需要点击 导出解决方案 讲这个解决方案作为 非托管解决方案 导出。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610215947037-522544778.jpg)
导出的解决方案是一个以 .zip 结尾的压缩文件,右击它,选择 全部提取 。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220017828-871945598.jpg)
全部提取后的文件夹中有一个名称为 customizations.xml 的文件便是要手工编辑的文件了。为了更好的编辑这个文件,最好有些智能提示,这个我们可以利用SDK\Schemas中的架构文件。我们要用到的是名称为 CustomizationsSolution.xsd 的架构文件,但是这个架构文件引用了其他的架构文件,所以还是将这些架构文件放在同一个目录下为好。虽然用记事本也可以编辑这个 customizations.xml 文件,但是为了更加高效和准确我们使用Visual Studio来做。将 customizations.xml 使用Visual Studio打开。将 SDK\Schemas 文件夹中的如下文件 复制到Visual Studio 的安装目录:[安装目录]\Program Files (x86)\Microsoft Visual Studio X.0\Xml\Schemas ,比如我这里是 C:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas 这个文件夹。
CustomizationsSolution.xsd
fetch.xsd
FormXml.xsd
isv.config.xsd
RibbonCore.xsd
RibbonTypes.xsd
RibbonWSS.xsd
SiteMap.xsd
SiteMapType.xsd
VisualizationDataDescription.xsd
fetch.xsd
FormXml.xsd
isv.config.xsd
RibbonCore.xsd
RibbonTypes.xsd
RibbonWSS.xsd
SiteMap.xsd
SiteMapType.xsd
VisualizationDataDescription.xsd
然后右击要编辑的 customizations.xml 文件 选择属性:
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220056438-1508489969.jpg)
然后还要将光标放入这个文件的内容中,就可以看到 属性 那里有个架构,点击架构旁边的 [...] 图标,出来弹出对话框,但是因为这里没有我们要用到的 CustomizationsSolution.xsd 文件,所以点击添加按钮。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220126198-19037251.jpg)
找到我们之前放在Visual Studio安装目录的CustomizationsSolution.xsd 文件添加进来,确保 使用列的勾勾处于选中状态(也就是选择 使用此架构 选项),然后点击 确定 按钮将其关闭。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220155218-269778019.jpg)
然后就是在智能提示下修改解决方案中的 customizations.xml 文件了。找到XML文档中的 RibbonDiffXml 元素,可以看到没有编辑过的这个元素的值如下:
<RibbonDiffXml> <CustomActions /> <Templates> <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates> </Templates> <CommandDefinitions /> <RuleDefinitions> <TabDisplayRules /> <DisplayRules /> <EnableRules /> </RuleDefinitions> <LocLabels /> </RibbonDiffXml>
将 CustomActions 元素从空元素改成包括子元素的写法,输入 < ,你会发现有智能提示了。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220246374-1045856097.jpg)
我这里修改很简单,增加了两个隐藏按钮的XML元素HideCustomAction,Location属性指出了它隐藏的按钮的ID,这个ID可以从导出的实体Ribbon定义文件中找到。HideActionId属性应该是保持唯一即可。
<RibbonDiffXml> <CustomActions> <HideCustomAction Location="Mscrm.HomepageGrid.new_area.DeleteMenu" HideActionId="Mscrm.HomepageGrid.new_area.DeleteMenu.HideAction" /> <HideCustomAction Location="Mscrm.Form.new_area.Delete" HideActionId="Mscrm.Form.new_area.Delete.HideAction" /> </CustomActions> <Templates> <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates> </Templates> <CommandDefinitions /> <RuleDefinitions> <TabDisplayRules /> <DisplayRules /> <EnableRules /> </RuleDefinitions> <LocLabels /> </RibbonDiffXml>
修改保存后选中之前解决方案中的所有的文件,右击,选择 发送到 > 压缩(Zipped)文件夹。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220332280-767848021.jpg)
然后将这个压缩为文件导入到系统中,并在最后页面点击 发布所有自定义项 以发布你的更改。
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220405214-382195177.jpg)
然后我们刷新浏览器去看看效果,列表界面的删除按钮(组)不见了:
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220435065-1027735837.jpg)
实体表单界面的删除按钮也不见了:
![](https://img2018.cnblogs.com/blog/779910/201906/779910-20190610220506330-1640819733.jpg)
当然不要以为看不到删除按钮就删除不了记录,还是可以通过其他方法删除的,比如高级查找功能,批量删除记录功能,通过代码的方式等等,最好不让用户删除的方式当然是移除用户对这个实体的删除权限。