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