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.