Crm 2011 - 如何根据属性值设置默认表单(不使用Javascript)?

时间:2013-05-02 14:31:42

标签: forms dynamics-crm-2011

我有一点让我疯狂的要求: 我们有8种不同的联系实体形式。 我们还有一个包含8个选项的选项列表。 我们的想法是,基于所选的选项,我们可以打开Contact记录,默认显示一个特定的表单,不使用JAVASCRIPT以避免性能问题(每个记录必须加载两次)。例如:

形式:
 表格1  表格2  表格3

选择列表值 - 默认表单:

表格1  表格2  表格3

如果选择了表格3(选择列表值),则下次打开该记录时,默认情况下应显示表格。

如果选择了表单1(选择列表值),则下次打开该记录时,默认情况下应显示表单。

我已经在systemform实体中注册了一个插件,在RetrieveFilteredForms消息中,更新了userentityuisettings表,我已经能够设置一个" DEFAULT"无论上次打开的表单是什么,每次打开记录时都会显示。

我已经在联系人实体上注册了一个插件,在Retrieve消息中,更新了userentityuisettings表,但我发现Crm只查询表一旦没有更新属性,以下时间Crm采用默认值从缓存中打开值的表单。

3 个答案:

答案 0 :(得分:3)

这是一个老问题,但由于我在搜索此问题时出现,我想添加我的解决方案。

我们使用Dynamics CRM 2013.据我所知,2011年的更高版本也支持这种技术。

打开实体时显示的表单由一些内容决定 - 表单的默认表单,安全角色和后备设置以及当前用户为该实体使用的最后一个表单。我们向提问者提出了类似的问题,我们希望根据表单的值显示不同的帐户表单。我们也厌倦了javascript技术所受的持续重载/刷新。

我发现了一些博客帖子(特别是这一篇:http://gonzaloruizcrm.blogspot.com/2014/11/avoiding-form-reload-when-switching-crm.html),其中提到可以在实体的Retrieve中编写一个插件,允许您从UserEntityUISettings中读出值(LastViewedFormXml)哪种形式的商店是最后使用的。如果它不是您想要的形式,您可以写入所需的值。这样可以避免javascript表单刷新。

我必须修改我发现的样本中的一些代码才能使其工作,但我对结果感到满意。您需要使用CrmSvcUtil生成实体类并将其包含在项目中。您可以从表单编辑器的URL获取表单guid。

using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;

namespace CRM.Plugin.AccountFormSwitcher
{
    public class Plugin : IPlugin
    {
        public enum accountType
        {
            Customer =  100000000,
            Vendor =     100000001,
            Partner = 100000002,
            Other =    100000003
        }

        public const string CustomerAccountFormId = "00000000-E53C-4DF4-BC99-93856EDD168C";
        public const string VendorAccountFormId = "00000000-E49E-4197-AB5E-F353EF0E806E";
        public const string PartnerAccountFormId = "00000000-B8C6-4E2B-B84E-729AA11ABE61";
        public const string GenericAccountFormId = "00000000-8F42-454E-8E2A-F8196B0419AF";

        public const string AccountTypeAttributeName = "cf_accounttype";

        public void Execute(IServiceProvider serviceProvider)
        {
            if (serviceProvider == null)
            {
                throw new ArgumentNullException("serviceProvider");
            }

            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            var pluginContext = (IPluginExecutionContext)context;
            if (pluginContext.Stage == 20) //pre-operation stage
            {
                var columns = (ColumnSet)pluginContext.InputParameters["ColumnSet"];
                if (!columns.Columns.Contains(AccountTypeAttributeName))
                    columns.AddColumn(AccountTypeAttributeName);
            }
            else if (pluginContext.Stage == 40) //post-operation stage
            {
                EntityReference currentEntity = (EntityReference)context.InputParameters["Target"];
                if (currentEntity == null)
                    return;

                var query = new QueryExpression(Account.EntityLogicalName);
                query.Criteria.AddCondition("accountid", ConditionOperator.Equal, currentEntity.Id);
                query.ColumnSet = new ColumnSet(AccountTypeAttributeName);
                var accounts = service.RetrieveMultiple(query).Entities;
                Account currentAccount = (Account)accounts[0];

                SetForm(currentAccount, service, context.UserId);
            }
        }

        private void SetForm(Account account, IOrganizationService service, Guid userId)
        {
            var query = new QueryExpression(UserEntityUISettings.EntityLogicalName);
            query.Criteria.AddCondition("ownerid", ConditionOperator.Equal, userId);
            query.Criteria.AddCondition("objecttypecode", ConditionOperator.Equal, Account.EntityTypeCode);
            query.ColumnSet = new ColumnSet("lastviewedformxml");
            var settings = service.RetrieveMultiple(query).Entities;

            // Some users such as SYSTEM have no UserEntityUISettings, so skip.
            if (settings == null || settings.Count != 1 || account.cf_AccountType == null) return;

            var setting = settings[0].ToEntity<UserEntityUISettings>();
            string formToUse;
            switch ((accountType)account.cf_AccountType.Value)
            {
                case accountType.Customer:
                    formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", CustomerAccountFormId);
                    break;
                case accountType.Vendor:
                    formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", VendorAccountFormId);
                    break;
                case accountType.Partner:
                    formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", PartnerAccountFormId);
                    break;
                case accountType.Other:
                    formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", GenericAccountFormId);
                    break;
                default:
                    formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", GenericAccountFormId);
                    return;
            }

            // Only update if the last viewed form is not the one required for the given opportunity type
            if (!formToUse.Equals(setting.LastViewedFormXml, StringComparison.InvariantCultureIgnoreCase))
            {
                var s = new UserEntityUISettings { Id = setting.Id, LastViewedFormXml = formToUse };
                service.Update(s);
            }
        }
    }
}

为了解决提问者的问题,只咨询UserEntityUISettings一次,我不确定为什么会这样。但是,当触发属性发生变化时,为什么不使用javascript来更改表单?我所做的和我没有遇到插件没有显示所需的任何问题。

答案 1 :(得分:0)

编辑:之后指定的OP需要一个没有javascript的解决方案,我留下这个回复以供将来参考。

您可以使用javascript,在OnLoad事件中检查选项列表值并导航到所需的表单。检查此代码作为示例

var value = Xrm.Page.getAttribute("new_optionset").getValue();

switch(value) {
case 100000000:
   Xrm.Page.ui.formSelector.items.get(0).navigate();
   break;
case 100000001:
   Xrm.Page.ui.formSelector.items.get(1).navigate();
   break;
case 100000002:
   Xrm.Page.ui.formSelector.items.get(2).navigate();
   break;
/// ... other cases here
default:
   // default form to open when there is no value
   Xrm.Page.ui.formSelector.items.get(0).navigate();
}

答案 2 :(得分:0)

这是一个古老而又好的...我使用CRM规则生成隐藏选项卡和显示选项卡操作,这些操作基本上将每个用户角色显示为不同的形式。

步骤:

  1. 创建一个包含您要显示的所有字段的大型表单(如果您已经有很多表单,则会包含所有表单中的所有字段)。
  2. 将表单整理到TABS中,每个标签显示“一种形式”的数据。 (您还可以为每个用户组设置许多TABS)。通常,我创建一个“常规”选项卡,其中包含将设置表单其余部分的密钥选项集,以及角色/用户组/表单中常见的任何字段,如状态,名称等... 3)通过取消选中管理界面中这些选项卡表单属性表单上的可见框,隐藏除常规选项卡以外的所有选项卡。 4)使用CRM规则(crm-rules.com),然后您可以在其中引入元数据,表单以及所有选项卡和部分。然后你只需要为你想要展示的每个'表单'写一个规则......每个规则都是这种格式:

    • 如果User_Role包含'Sales'那么显示标签:销售
    • 如果User_Role包含'营销'那么显示标签:营销
  3. 当然,您也可以使用选项集或表单上的任何字段作为条件来执行此操作...此方法的一个好处是,如果用户跨越角色边界(或某些用户属于可以访问多种形式的安全角色),这种技术可以同时显示两种形式......

    HTH某人,CRM规则(www.crm-rules.com)生成JavaScript以实现这一目标......