Pessoal,
Seguindo a série de posts sobre o USD, irei escrever neste post sobre os Events!
Para ver os posts anteriores, acesse os links (estão por ordem de publicação do mais recente para o mais antigo):
CRM – Toolbars e Buttons (USD)
CRM Utilidades do USD (Unified Service Desk)
Diferentemente das Action Calls, os Events representam ações (triggers) que são pré determinadas pelos controles, elas irão possuir e executar a partir do momento em que sejam adicionados ou interagidos no USD.
De acordo com o tipo do controle, nativamente, temos alguns Eventos que sempre podem ser adicionados ao controle USD:
Hosted Control do tipo CRM Page
Apesar de termos eventos padrões, podemos criar nossos próprios eventos e decidirmos quando que eles serão adicionados.
Um outro ponto muito bom dos eventos é que conseguimos adicionar quantas Action Calls necessitarmos em um único evento, além disso, é possível determinar a ordem em que as Actions irão ser executadas. Um bom exemplo disso é o hosted control “CRM Global Manager”, ao ser inicializado, ou seja no evento “DesktopReady”, ele executa por padrão as seguintes actions calls:
Como também já tive que fazer alguns exemplos nos posts anteriores que envolvem o uso de Events, vou inserir neste post, um forma diferente de usarmos…
No post sobre Action Calls, nos dois exemplos estão realizando via C# uma chamada a uma Action Call, podemos fazer da mesma forma, porém usando Events! Assim, conseguimos ter duas coisas a mais:
1 – Ao criar e executar um Event, conseguimos ter um reaproveitamento de código
2 – Podemos acionar mais do que uma Action Call com apenas um acionamento de um único Event
Deste modo, devemos trocar uma chamada a Action:
// Action var action = new ActionDefinition { Application = "APPLICATION_NAME", // Hosted Control Action = "ACTION_NAME", // Action ActionData = "DATA_VALUE" // Data }; // Execute Actions CRMWindowRouter.ExecuteActions(localSessionManager.ActiveSession, new List<ActionDefinition> { action }, string
Por uma chamada à um Event:
// Event FireEvent("EVENT_NAME");
No post de Action Calls, fiz um Custom Hosted Control que ao selecionarmos a opção “Ocorrência” do Radio Button e clicar no botão “Ok”, executava uma chamada de uma Action Call.
Agora, fiz um pequeno ajuste, para um nova opção no radio button “Ocorrência e Oportunidade”, que ao selecionarmos e submetermos abrirá duas novas abas (temos que possuir uma sessão com o cliente aberta):
O código, muda muito pouco…
XAML:
<USD:DynamicsBaseHostedControl x:Class="CustomUSDHostedControl.USDControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:USD="clr-namespace:Microsoft.Crm.UnifiedServiceDesk.Dynamics;assembly=Microsoft.Crm.UnifiedServiceDesk.Dynamics" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ToolBarTray Name="ProgrammableToolbarTray" Grid.Row="0" Focusable="false"/> <!-- this is where any toolbar assigned to this control will go --> <Button Name="button" Click="button_Click" HorizontalAlignment="Left" Margin="64,202,0,0" Grid.Row="1" Content="Ok" VerticalAlignment="Top" Width="52" Height="22" /> <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="78,47,0,0" Grid.Row="1" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/> <RadioButton x:Name="radioButtonInfo" Content="Informação" GroupName="options" HorizontalAlignment="Left" Margin="78,94,0,0" Grid.Row="1" VerticalAlignment="Top"/> <RadioButton x:Name="radioButtonOcor" Content="Ocorrência" GroupName="options" HorizontalAlignment="Left" Margin="174,94,0,0" Grid.Row="1" VerticalAlignment="Top" /> <RadioButton x:Name="radioButtonOcorOp" Content="Ocorrência e Oportunidade" GroupName="options" HorizontalAlignment="Left" Margin="80,133,0,0" Grid.Row="1" VerticalAlignment="Top" /> </Grid> </USD:DynamicsBaseHostedControl>
C# (atenção no evento de click do botão “Ok” – button_Click):
// ===================================================================== // This file is part of the Microsoft Dynamics CRM SDK code samples. // // Copyright (C) Microsoft Corporation. All rights reserved. // // This source code is intended only as a supplement to Microsoft // Development Tools and/or on-line documentation. See these other // materials for detailed information regarding Microsoft code samples. // // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // ===================================================================== using System; using System.Globalization; using System.Windows; using Microsoft.Crm.UnifiedServiceDesk.CommonUtility; using Microsoft.Crm.UnifiedServiceDesk.Dynamics; using System.Collections.Generic; using Microsoft.Crm.UnifiedServiceDesk.Dynamics.Utilities; namespace CustomUSDHostedControl { /// <summary> /// Interaction logic for USDControl.xaml /// This is a base control for building Unified Service Desk Aware add-ins /// See USD API documentation for full API Information available via this control. /// </summary> public partial class USDControl : DynamicsBaseHostedControl { #region Vars /// <summary> /// Log writer for USD /// </summary> private TraceLogger LogWriter = null; #endregion /// <summary> /// UII Constructor /// </summary> /// <param name="appID">ID of the application</param> /// <param name="appName">Name of the application</param> /// <param name="initString">Initializing XML for the application</param> public USDControl(Guid appID, string appName, string initString) : base(appID, appName, initString) { InitializeComponent(); // This will create a log writer with the default provider for Unified Service desk LogWriter = new TraceLogger(); #region Enhanced LogProvider Info // This will create a log writer with the same name as your hosted control. // LogWriter = new TraceLogger(traceSourceName:"MyTraceSource"); // If you utilize this feature, you would need to add a section to the system.diagnostics settings area of the UnifiedServiceDesk.exe.config //<source name="MyTraceSource" switchName="MyTraceSwitchName" switchType="System.Diagnostics.SourceSwitch"> // <listeners> // <add name="console" type="System.Diagnostics.DefaultTraceListener"/> // <add name="fileListener"/> // <add name="USDDebugListener" /> // <remove name="Default"/> // </listeners> //</source> // and then in the switches area : //<add name="MyTraceSwitchName" value="Verbose"/> #endregion } /// <summary> /// Raised when the Desktop Ready event is fired. /// </summary> protected override void DesktopReady() { // this will populate any toolbars assigned to this control in config. PopulateToolbars(ProgrammableToolbarTray); base.DesktopReady(); } /// <summary> /// Raised when an action is sent to this control /// </summary> /// <param name="args">args for the action</param> protected override void DoAction(Microsoft.Uii.Csr.RequestActionEventArgs args) { // Log process. LogWriter.Log(string.Format(CultureInfo.CurrentCulture, "{0} -- DoAction called for action: {1}", this.ApplicationName, args.Action), System.Diagnostics.TraceEventType.Information); #region Example process action //// Process Actions. //if (args.Action.Equals("your action name", StringComparison.OrdinalIgnoreCase)) //{ // // Do some work // // Access CRM and fetch a Record // Microsoft.Xrm.Sdk.Messages.RetrieveRequest req = new Microsoft.Xrm.Sdk.Messages.RetrieveRequest(); // req.Target = new Microsoft.Xrm.Sdk.EntityReference( "account" , Guid.Parse("0EF05F4F-0D39-4219-A3F5-07A0A5E46FD5")); // req.ColumnSet = new Microsoft.Xrm.Sdk.Query.ColumnSet("accountid" , "name" ); // Microsoft.Xrm.Sdk.Messages.RetrieveResponse response = (Microsoft.Xrm.Sdk.Messages.RetrieveResponse)this._client.CrmInterface.ExecuteCrmOrganizationRequest(req, "Requesting Account"); // // Example of pulling some data out of the passed in data array // List<KeyValuePair<string, string>> actionDataList = Utility.SplitLines(args.Data, CurrentContext, localSession); // string valueIwant = Utility.GetAndRemoveParameter(actionDataList, "mykey"); // asume there is a myKey=<value> in the data. // // Example of pushing data to USD // string global = Utility.GetAndRemoveParameter(actionDataList, "global"); // Assume there is a global=true/false in the data // bool saveInGlobalSession = false; // if (!String.IsNullOrEmpty(global)) // saveInGlobalSession = bool.Parse(global); // Dictionary<string, CRMApplicationData> myDataToSet = new Dictionary<string, CRMApplicationData>(); // // add a string: // myDataToSet.Add("myNewKey", new CRMApplicationData() { name = "myNewKey", type = "string", value = "TEST" }); // // add a entity lookup: // myDataToSet.Add("myNewKey", new CRMApplicationData() { name = "myAccount", type = "lookup", value = "account,0EF05F4F-0D39-4219-A3F5-07A0A5E46FD5,MyAccount" }); // if (saveInGlobalSession) // { // // add context item to the global session // ((DynamicsCustomerRecord)((AgentDesktopSession)localSessionManager.GlobalSession).Customer.DesktopCustomer).MergeReplacementParameter(this.ApplicationName, myDataToSet, true); // } // else // { // // Add context item to the current session. // ((DynamicsCustomerRecord)((AgentDesktopSession)localSessionManager.ActiveSession).Customer.DesktopCustomer).MergeReplacementParameter(this.ApplicationName, myDataToSet, true); // } //} #endregion if (args.Action.Equals("ButtonClick", StringComparison.OrdinalIgnoreCase)) { // Get Data Value var dataValue = args.DataObject.ToString(); // Set Data Value in TextBox textBox.Text = dataValue; } base.DoAction(args); } /// <summary> /// Raised when a context change occurs in USD /// </summary> /// <param name="context"></param> public override void NotifyContextChange(Microsoft.Uii.Csr.Context context) { base.NotifyContextChange(context); } #region User Code Area private void button_Click(object sender, RoutedEventArgs e) { // Verify if radio "Ocorrência e Oportunidade" is Checked if (radioButtonOcorOp.IsChecked == true) { // Event FireEvent("Event Open Incident and Opportunity"); textBox.Text = "Incident and Opportunity Opened!"; } // Verify if radio "Ocorrência" is Checked else if (radioButtonOcor.IsChecked == true) { // Action var openIncident = new ActionDefinition { Application = "Incident", // Hosted Control Action = "New_CRM_Page", // Action ActionData = "LogicalName=incident" // Data }; // Execute Actions CRMWindowRouter.ExecuteActions(localSessionManager.ActiveSession, new List<ActionDefinition> { openIncident }, string.Empty, new Dictionary<string, string>()); textBox.Text = "Incident Opened!"; } else { textBox.Text = "Button Fired!"; } } #endregion } }
Compile o projeto e adicione a DLL dentro da pasta raiz do USD!
No CRM, temos que criar um Hosted Control Evento, duas Action Calls e uma Windows Navigation Rule.
Caso você não possua um Hosted Control do tipo CRM Page que seja para uma Oportunidade, precisará criar um. Abra seu CRM, navegue me Configurações > Unified Service Desk > Hosted Controls > Novo:
Precisamos informar:
- Name – O nome de seu hosted control
- USD Component Type – CRM Page
- Display Group – “MainPanel”, não é global é só será aberto quando alguma ação for disparada, quando ocorrer, será apresentado no MainPanel
Agora localize o Hosted Control que criamos anteriormente no post de Action Calls “CustomUSDHostedControl” (Configurações > Unified Service Desk > Hosted Controls):
Abra o relacionamento do Hosted Control com seus Eventos:
Depois devemos criar nosso Evento, basta informar um nome. Ao salvar, podemos criar as duas Actions:
A primeira Action, abrirá uma Ocorrência:
Devemos informar:
- Name – O nome de sua action call
- Hosted Control – “CustomUSDHostedControl”, o nome do nosso Custom Hosted Control
- Action – “New_CRM_Page”, uma nova página do CRM
- Data – “LogicalName=incident”, o formulário de Ocorrências do CRM
A segunda Action Call, abrirá o formulário de Oportunidade:
Devemos informar:
- Name – O nome de sua action call
- Hosted Control – “CustomUSDHostedControl”, o nome do nosso Custom Hosted Control
- Action – “New_CRM_Page”, uma nova página do CRM
- Data – “LogicalName=incident”, o formulário de Ocorrências do CRM
Por fim, precisamos criar um Window Navigation Rule, para que a aba seja aberta (RouteWindow). A ocorrência abrirá sem problemas, pois já temos uma regra para ela nativamente.
Navegue em Configurações > Unified Service Desk > Windows Navigation Rules > Novo:
Informe:
Devemos informar:
- Name – O nome de sua window navigation rule
- Order – A ordem de execução, insira um número alto, para garantirmos que será uma das últimas ações a serem executadas
- Entity – “opporunity”, se não tiver cadastrada, crie um novo registro com o nome “opporunity”
- Action – “Route Windows”, quando um janela da entidade Oportunidade for inserida no USD
- Target Tab – “Opportunity”, o nome do hosted control que possui o form da Oportunidade
- Show Tab – “Opportunity”, o nome do hosted control que possui o form da Oportunidade
- Hide navigation Bar – Marcar a caixa de seleção
Pronto, abra seu USD, inicie um sessão com um cliente e verifique o resultado!
Para maiores informações, consulte os links oficiais:
Events
Create a user-defined event
[]’s,
Tiago Cardoso
Olá, Parabéns pelo Post.
Você por acaso saberia dizer quais são os Events padrões dos controles hospedados customizados (WPF)?
Sei que existe o DesktopReady, Close, etc…
Na verdade, gostaria de saber se é possível disparar uma ação quando a aba de um controle hospedado for clicado.
CurtirCurtir
Ola Pedro,
Nao sei o seu cenario completo, mas talvez um pouco de JS no load do form que esta na aba seria uma solucao, veja esse post aqui:
https://neilparkhurst.com/2016/06/19/usd-call-events-from-javascript/
Att,
Tiago
CurtirCurtir