Wednesday, February 20, 2013

CDC Software Pivotal CRM 6.0: How to execute another client task method with parameters.

Yes it is possible to call another client task method with parameters.
It can be useful for specific things like using Client Forms as custom dialogs.

The caller:
// Get action service
IActionService actionService = ClientContext.ClientAPIService.GetService<IActionService>();

// Create action target object
IClientTaskActionTarget clientTaskActionTarget = actionService.CreateActionTarget<IClientTaskActionTarget>();
clientTaskActionTarget.ClientTask = "MyCompany.PivotalProject.Client";
clientTaskActionTarget.ClientTaskMethod = "MyMethod";
clientTaskActionTarget.Parameters = new object[] { 
 "parameter 1", "parameter 2", "parameter 3"
};

// Create action and execute it.
IAction action = actionService.CreateAction("MyActionName", ActionCommand.Show, ActionContent.ClientTask, clientTaskActionTarget);
actionService.ExecuteAction(action);
The calling method:
public void MyMethod(string p1, string p2, string p3){
 // ... Do something
}

Wednesday, January 9, 2013

CDC Software Pivotal CRM 6.0: Adding custom button to buttons bar.

Someone asked me today how to add custom button bar button to a client form.
Very simple :)

// Get action service
IActionService actionService = ClientContext.ClientAPIService.GetService<IActionService>();

// Create client task action target
IClientTaskActionTarget clientTaskActionTarget = actionService.CreateActionTarget<IClientTaskActionTarget>();
clientTaskActionTarget.ClientTask = "Pivotal.Client.FormTask";
clientTaskActionTarget.ClientTaskMethod = "CustomButtonClickHandler";

// Create action            
IAction action = actionService.CreateAction("CustomButtonClickActionName", ActionCommand.Show, ActionContent.ClientTask, clientTaskActionTarget);

// Create custom button (requires Pivotal.Engine.UI.DataTypes.dll)
ButtonBarButton button = new ButtonBarButton(){
 Name = "CustomButton",
 DisplayName = "My Custom Button",
 Enabled = true
};

// Set custom button action
button.SetAction(action);

// Add custom button to a center content buttons bar
this.ButtonBar.Buttons.Add(button);

Sunday, November 25, 2012

CDC Software Pivotal CRM 6.0: Using Pivotal Input Dialog.


Pivotal Input Dialog may be useful if you want to ask user some input parameters without creating a new client form.
I didn't find any documentation about how exactly to use Pivotal Input Dialog.
So I'm going to publish some code examples here how to use it.

Required dlls:

Pivotal.Engine.Client.Services.Interfaces.dll
Pivotal.Engine.UI.DataTypes.dll

// Get input dialog service
IInputDialogService inputDialogService = ClientContext.ClientAPIService.GetService<IInputDialogService>();
DialogParam dialogParameter = new DialogParam();
dialogParameter.FormParams = new CdcSoftware.Pivotal.Engine.UI.DataTypes.FormParams.InputParamsCollection();

// 1. Foreign Key
Table companyTable = this.SystemClient.UserProfile.GetMetaItem<Table>("Company");
InputParam foreignKeyInputParam = new InputParam()
{
    Label = "Company",
    Type = InputParamType.RForeignField,
    IsRequired = true,
    Enums = companyTable.Id
};
dialogParameter.FormParams.Add(foreignKeyInputParam);

// 2. Single value fields: Date, Boolean, Integer, Double and etc
InputParam dateInputParam = new InputParam() { Label = "Date", Type = InputParamType.Date };
dialogParameter.FormParams.Add(dateInputParam);

InputParam boolInputParam = new InputParam() { Label = "Boolean", Type = InputParamType.Boolean };
dialogParameter.FormParams.Add(boolInputParam);

InputParam intInputParam = new InputParam() { Label = "Integer", Type = InputParamType.Integer };
dialogParameter.FormParams.Add(intInputParam);

// 2. Combo, ListBox
object[] comboValues = new object[] { "value 1", "value 2" };
InputParam comboInputParam = new InputParam() { Label = "Date", Type = InputParamType.RCombo, Enums = comboValues };
dialogParameter.FormParams.Add(comboInputParam);

// Set dialog type
dialogParameter.DialogType = ModalDialogTypeEnum.modalDialogParamsAndDescription;

// Show dialog
inputDialogService.ShowDialog(dialogParameter, "Title");

// Get parameter values
if (foreignKeyInputParam.Value != null)
{
    Id companyId = Id.Create(foreignKeyInputParam.Value);
}

if (intInputParam.Value != null)
{
    int intValue = TypeConvert.ToInt32(intInputParam.Value);
}
You can discover other input parameters types by yourself.

Sunday, August 5, 2012

CDC Software Pivotal CRM 6.0: How to get acces to SearchView.SearchData.ResultsViewControl control.

We can't modify SearchView.SearchData.ResultsViewControl in a usual way because it has an internal get accessor.
But we can use reflection.

Here is an example how to change SearchView rows text color deppending on received data.

1. Add the following dll references to your project:
  • Pivotal.CommonControls.dll
  • CdcSoftware.Ios.UI.dll

2. Register "OnSearchCompleted" notification event handler:
[NotificationEvent("OnSearchCompleted", Table = "Support_Incident")]
public void OnSupportIncidentSearchCompleted(object notifyParams)
{
 ...
}

3. Get DataGridView control via reflection.
CdcSoftware.Pivotal.CommonControls.ResultsViewControl resultsViewControl = searchView.SearchData.GetType().GetProperty("ResultsViewControl").GetValue(searchView.SearchData, null) as CdcSoftware.Pivotal.CommonControls.ResultsViewControl;
if (resultsViewControl != null)
{
CdcSoftware.Pivotal.CommonControls.PivotalDataGridView dataGridView = resultsViewControl.GetType().GetField("_dataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(resultsViewControl) as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
}

4. Modify you want.

The full code example:
[NotificationEvent("OnSearchCompleted", Table = "Support_Incident")]
        public void OnSupportIncidentSearchCompleted(object notifyParams)
        {
            ISearchView searchView = ClientContext.ClientAPIService.GetActiveContentObject() as ISearchView;
            if (searchView != null)
            {
                //Get ResultsViewControl
                CdcSoftware.Pivotal.CommonControls.ResultsViewControl resultsViewControl = searchView.SearchData.GetType().GetProperty("ResultsViewControl").GetValue(searchView.SearchData, null) as CdcSoftware.Pivotal.CommonControls.ResultsViewControl;

                if (resultsViewControl != null)
                {
                    //Get DataGridView control
                    CdcSoftware.Pivotal.CommonControls.PivotalDataGridView dataGridView = resultsViewControl.GetType().GetField("_dataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(resultsViewControl) as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
                    
                    //Attach RowPostPaint event
                    dataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler((object sender, DataGridViewRowPostPaintEventArgs e) =>
                    {
                        CdcSoftware.Pivotal.CommonControls.PivotalDataGridView pivotalDataGridView = sender as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
                        if (dataGridView.Columns.Contains("Status_Id@Rn_Descriptor"))
                        {
                            //Color closed incidents
                            string columnTextValue = Convert.ToString(pivotalDataGridView.Rows[e.RowIndex].Cells["Status_Id@Rn_Descriptor"].Value);
                            if (columnTextValue.Contains("Closed"))
                            {
                                pivotalDataGridView.Rows[e.RowIndex].DefaultCellStyle.ForeColor = System.Drawing.Color.Red;
                            }
                        }
                    });
                }
            }
        }

Regards,
Max Shafranski

Wednesday, August 1, 2012

Another way to preview reports and other file types in Pivotal Client.

Another trivial way to display reports and other file types saved in database in Pivotal Client.

Scenario: display report as PDF file in Pivotal Client by pressing Task Pad item.

Client Task (click event handler):
// Get file content from server
byte[] fileContent = Globals.SystemClient.ExecuteServerTask("Server Task Name", "GetReportContent", new Type[] { typeof(Id) }, new object[] { recordId }) as byte[];

// Create temp file name
string fileName = String.Format("{0}.{1}", Guid.NewGuid(), ".pdf");
string tempFilePath = Path.Combine(System.IO.Path.GetTempPath(), fileName);

using (MemoryStream stream = new MemoryStream(fileContent))
{
 using(FileStream fileStream = new FileStream(tempFilePath, FileMode.Create, System.IO.FileAccess.Write))
 {
  stream.WriteTo(fileStream);
  fileStream.Flush();
  fileStream.Close();
    
  // Open file using windows shell
  Process.Start(tempFilePath);
 }
}
Server Task:
[TaskExecute]
public byte[] GetReportContent(Id recordId)
{
 try
 {
  SystemReport report = this.SystemServer.GetMetaItem<SystemReport>("Report Name") as SystemReport;
  ReportRunner reportRunner = this.SystemServer.CreateReportRunner(report);
  reportRunner.ReportOutputFormat = ReportOutputFormat.Pdf;
  return reportRunner.Run(ReportFilter.SingleRow, recordId, null);
 }
 catch (Exception ex)
 {
  throw new PivotalApplicationCoreException(ex.Message, ex);
 }
}

How to send emails with styles and embedded images using Pivotal API.

A lot of work.
A lot of projects.
But I've got some free time for Pivotal.

Here is an example how to send formatted emails with styles and embedded images via Pivotal API:

Server Task code:
CdcSoftware.Pivotal.Engine.Mail.EmailMessage emailMessage =
   this.SystemServer.CreateMessage();
emailMessage.To.Add("myemail@email.com");
emailMessage.MimeHtmlBodyFileName = @"C:\Email.htm";
emailMessage.Subject = "Test";
emailMessage.Body = "";
emailMessage.Send();

Email.htm file content:
<html>
 <head>
  <style type="text/css">
   body { 
    background-color:Green;
    font-size: 3em;
   }
  </style>
 </head>
<body>
 Test email:
 <img src="image.jpg"/>
</body>
</html>

Of course, you can save html email templates in database, retrieve their content, save as temp file and then use the code above.
Also it is recommended to use SP 10 or later.

Tuesday, March 27, 2012

Using custom grids in Client Forms.

Sometimes we need to build our custom grid to display/manipulate different data.
We can use a standart DataGridView control from System.Windows.Forms.dll, but it doesn't match to Pivotal color scheme.
Therefore there is DataGridViewWithStyle pivotal control in CdcSoftware.Ios.UI.dll that looks like a common Pivotal secondary control.

Here is an example how to use it:

1. Add PivotalCustomControlContainer to a client form
2. Write some client code in form client task:

// Get container control
PivotalCustomControlContainer customGridContainer = this.FormControl.GetControlByName("CustomGridContainer") as PivotalCustomControlContainer;

// Declare custom grid properties and columns
DataGridViewWithStyle customGrid = new DataGridViewWithStyle();
customGrid.Dock = DockStyle.Fill;
customGrid.AllowUserToAddRows = false;
customGrid.AllowUserToDeleteRows = false;
customGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Id", HeaderText = "Id", Visible = false });
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Name", HeaderText = "Name", ReadOnly = true });
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Age", HeaderText = "Age", ReadOnly = true });

// Add custom grid to the container
customGridContainer.CustomControl = customGrid;

// Populate grid data
this.PopulateGrid(customGrid);

Thats all.

Regards,
Max Shafranski