0

I have a little requirement that is making me crazy: We have 8 different forms for the Contact Entity. We also have a pick list with 8 options. The idea is that based on the option selected we could open that Contact record showing by default a particular form WITHOUT USING JAVASCRIPT in order to avoid performance problems (each record has to be loaded twice). Example:

Forms:
Form 1
Form 2
Form 3

Pick List Values - Default Form:

Form 1
Form 2
Form 3

If Form 3(pick list value) is selected then, the next time I open that record, Form 3 should be displayed by default.

If Form 1(pick list value) is selected then, the next time I open that record, Form 1 should be displayed by default.

I've trayed registering a plugin at the systemform entity, in RetrieveFilteredForms message, updating the userentityuisettings table and I've been able to set a "DEFAULT" that is displayed every time the records is opened regardless the last opened form.

I've trayed registering a plugin at the contact entity, in Retrieve message, updating the userentityuisettings table but I found that Crm only consults the table Once if there is no attribute updated, the following times Crm take the the default form to open value from the cache.

4

3 回答 3

3

这是一个老问题,但因为它出现在我搜索这个问题的过程中,所以我想添加我的解决方案。

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

打开实体时显示的表单由几个因素决定 - 默认表单、表单的安全角色和回退设置以及当前用户为该实体使用的最后一个表单。我们遇到了与提问者类似的问题,我们希望根据表单的值显示不同的帐户表单。我们也厌倦了 javascript 技术所经历的不断的重新加载/刷新。

我发现了一些博客文章(特别是这篇文章:http: //gonzaloruizcrm.blogspot.com/2014/11/avoiding-form-reload-when-switching-crm.html),其中提到可以编写一个插件实体的检索,允许您从存储上次使用的表单的 UserEntityUISettings 中读出值 (LastViewedFormXml)。如果不是您想要的形式,您可以写入所需的值。这避免了刷新 javascript 表单。

我必须从我找到的示例中修改一些代码才能让它工作,但我对结果很满意。您需要使用 CrmSvcUtil 生成一个实体类并将其包含在项目中。您可以从表单编辑器的 url 获取表单指南。

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在触发属性更改时更改表单呢?我所做的,我没有遇到插件没有显示所需的任何问题。

于 2015-02-12T15:49:25.230 回答
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();
}
于 2013-05-02T15:45:17.557 回答
0

这是一个古老但很好的东西......我使用 CRM 规则来生成隐藏选项卡和显示选项卡操作,这些操作基本上向每个用户角色显示不同的表单。

脚步:

  1. 创建一个包含您要显示的所有字段的大型表单(如果您已经有许多表单,这将包括所有表单中的所有字段)。
  2. 将表格组织成 TABS,每个选项卡显示“一个表格”的数据。(您也可以为每个用户组设置多个 TABS)。通常,我创建一个“常规”选项卡,其中设置了将设置表单其余部分的关键选项,以及跨角色/用户组/表单通用的任何字段,如状态、名称等... 3)通过取消选中管理 UI 中这些选项卡表单属性表单上的可见框来隐藏除常规选项卡之外的所有选项卡。4) 使用 CRM 规则 (crm-rules.com),然后您可以引入元数据、表单以及其中的所有选项卡和部分。然后你只需要为你试图显示的每个“表单”编写一个规则......每个规则都是这种格式:

    • 如果 User_Role 包含“销售”,则显示选项卡:销售
    • 如果 User_Role 包含“营销”,则显示选项卡:营销

当然,您也可以使用选项集或表单上的任何字段作为条件来执行此操作...这种方法的好处之一是,如果用户跨越角色边界(或者某些用户是安全角色的一部分可以访问多个表单),这种技术同时显示它们两个表单......

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

于 2017-05-12T20:00:40.920 回答