CrmDateTimeControl

Now we will develop a date and time control to work with Microsoft Dynamics CRM’s CrmDateTime attribute type. The CrmDateTime control we will develop takes care of formatting the date and time in the user’s preferred format as defined in Microsoft Dynamics CRM. Based on the attribute’s metadata, we render an HTML input for entering the date or an HTML input for the date and a select box populated with time options. We also add a pop-up calendar to make it easy for the end user to select a date.

Programming the CrmDateTimeControl

Adding the CrmDateTimeControl class

  1. Right-click the ProgrammingWithDynamicsCrm4.Controls Project in Solution Explorer. Under Add, click New Item.

  2. In the Visual C# Items category, select the Class template.

  3. Enter CrmDateTimeControl.cs in the Name box and click OK.

The CrmDateTimeControl inherits from the System.Web.UI.CompositeControl class. In this case we use CompositeControl because the CrmDateTimeControl is composed of multiple child controls. As you will see, we will use these controls to handle the rendering of our final output. Example 14-3 provides the full source code for this control.

Example 14-3. CrmDateTimeControl source code

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using Microsoft.Crm.SdkTypeProxy;
using System.Web.UI.HtmlControls;
using System.Xml;
using Microsoft.Crm.Sdk.Metadata;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using System.Configuration;
using ProgrammingWithDynamicsCrm4.Utilities;

namespace ProgrammingWithDynamicsCrm4.Controls
{
    public class CrmDateTimeControl : CompositeControl
    {
        public string EntityName
        {
            get
            {
                object entityName = ViewState["EntityName"];

                if (entityName != null)
                    return (string)entityName;
                else
                    return String.Empty;
            }
            set
            {
                ViewState["EntityName"] = value;
            }
        }

        public string AttributeName
        {
            get
            {
                object attributeName = ViewState["AttributeName"];

                if (attributeName != null)
                    return (string)attributeName;
                else
                    return String.Empty;

            }
            set
            {
                ViewState["AttributeName"] = value;
            }
         }

         private DateTime _value = DateTime.MinValue;
         public DateTime Value
         {
             get
             {
                 DateTime returnVal = DateTime.MinValue;
                 string dateTime = String.Empty;

                 Table table = (Table)this.Controls[0];

                 // get an instance of the date input
                 HtmlInputText dateInput =
                                   (HtmlInputText)table.Rows[0].Cells[0].Controls[0];

                 dateTime = dateInput.Value;

                 if (table.Rows[0].Cells.Count > 2)
                 {
                     // get an instance of the time select
                     HtmlSelect timeSelect =
                                      (HtmlSelect)table.Rows[0].Cells[1].Controls[0];
                     dateTime += " " + timeSelect.Value;
                 }

                 if (!string.IsNullOrEmpty(dateTime))
                     returnVal = Convert.ToDateTime(dateTime);

                 return returnVal;
             }
             set
             {
                 _value = value;
             }
         }

         private void AddTimeOptions(HtmlSelect timeSelect, string timeFormat)
         {
             for (int hour = 0; hour < 24; hour++)
             {
                 for (int minute = 0; minute < 60; minute += 30)
                 {
                     DateTime time = new DateTime(2008, 5, 1, hour, minute, 0);
                     string formattedTime = time.ToString(timeFormat);

                     timeSelect.Items.Add(new ListItem(formattedTime));
                 }
             }
         }

         protected override void CreateChildControls()
         {
             Controls.Clear();
             CreateControlHierarchy();
             ClearChildViewState();
         }

         private void CreateControlHierarchy()
         {
             CrmService service =
      CrmServiceUtility.GetCrmService(ConfigurationManager.AppSettings["CrmServer"],
                                      ConfigurationManager.AppSettings["OrgName"]);

             // find the user's id
             WhoAmIRequest userRequest = new WhoAmIRequest();
             WhoAmIResponse userResponse =
                                        (WhoAmIResponse)service.Execute(userRequest);

             string fetch = String.Format(@"<fetch mapping='logical'>
                                            <entity name='usersettings'>
                                               <attribute name='timeformatstring' />
                                               <attribute name='dateformatstring' />
                                                <filter type='and'>
                                                    <condition
                                                         attribute='systemuserid'
                                                         operator='eq'
                                                         value='{0}' />
                                                </filter>
                                             </entity>
                                            </fetch>",
                                            userResponse.UserId.ToString());

             string fetchResults = service.Fetch(fetch);

             XmlDocument resultDoc = new XmlDocument();
             resultDoc.LoadXml(fetchResults);

             string timeFormat = resultDoc
                                    .DocumentElement
                                    .FirstChild
                                    .SelectSingleNode("timeformatstring").InnerText;
             string dateFormat = resultDoc
                                    .DocumentElement
                                    .FirstChild
                                    .SelectSingleNode("dateformatstring").InnerText;

             Table table = new Table();
             TableRow tr = new TableRow();

             table.Rows.Add(tr);

             TableCell dateTD = new TableCell();
             HtmlInputText dateInput = new HtmlInputText();
             dateInput.ID = "dateinput";

             if (this._value != DateTime.MinValue)
                 dateInput.Value = this._value.ToString(dateFormat);
                dateTD.Controls.Add(dateInput);

                tr.Cells.Add(dateTD);

                TableCell calendarTD = new TableCell();
                HtmlInputButton calButton = new HtmlInputButton();
                calButton.Value = "Cal";
                calButton.Attributes.Add("onclick",
         String.Format(@"window.open('crmdatetimecalendar.aspx?datecontrol='
                   + this.parentElement.previousSibling.firstChild.id
                   + '&dateformat={0}','cal','width=250,height=225,left=270,top=180'),"
                 , dateFormat));

                calendarTD.Controls.Add(calButton);

                tr.Cells.Add(calendarTD);

                MetadataService metadataService = CrmServiceUtility
                      .GetMetadataService(ConfigurationManager.AppSettings["CrmServer"],
                                         ConfigurationManager.AppSettings["OrgName"]);

                RetrieveAttributeRequest attributeRequest =
                                                         new RetrieveAttributeRequest();
                attributeRequest.EntityLogicalName = EntityName;
                attributeRequest.LogicalName = AttributeName;

                RetrieveAttributeResponse attributeResponse =
                   (RetrieveAttributeResponse)metadataService.Execute(attributeRequest);
                AttributeMetadata attributeMetadata =
                                                    attributeResponse.AttributeMetadata;

                DateTimeAttributeMetadata dateTimeAttribute =
                                           (DateTimeAttributeMetadata)attributeMetadata;

                if (dateTimeAttribute.Format.Value == DateTimeFormat.DateAndTime)
                {
                    TableCell timeTD = new TableCell();

                    HtmlSelect timeSelect = new HtmlSelect();
                    AddTimeOptions(timeSelect, timeFormat);

                    if (this._value != DateTime.MinValue)
                        timeSelect.Value = this._value.ToString(timeFormat);

                    timeTD.Controls.Add(timeSelect);
                    tr.Cells.Add(timeTD);
                }

                this.Controls.Add(table);
            }
      }
}

CrmDateTimeControl Properties

The CompositeControl base class provides us with a good starting point, but we still need to add some properties to our control. Table 14-3 lists all of the properties we need to add.

Table 14-3. CrmDateTimeControl Properties

Property Name

Type

Description

EntityName

string

Name of the Microsoft Dynamics CRM entity that the CrmDateTime attribute belongs to

AttributeName

string

Name of the CrmDateTime attribute

Value

DateTime

Gets or sets the value of the CrmDateTime control

Adding the Child Controls

The CrmDateTimeControl is composed of an outer HTML table that holds an HTML text input, a button for our calendar pop-up, and an HTML select box for the time options. These are all created and added to the Controls collection in the CreateControlHierarchy method.

The first thing we do in the CreateControlHierarchy method is find the current user’s systemuserid by making a WhoAmI call to the CrmService. Next we use a Fetch XML query to retrieve the user’s preferred date and time formats. Fetch XML is used in this case because QueryExpression does not support queries made against the usersettings entity.

After we create a Table control, we create the cell to hold the HTML text input for the date. If a value has been set on the CrmDateTimeControl, the user’s preferred date format is used to add the formatted date value to the input control.

The next table cell will hold the button for our calendar pop-up. Because we are creating a class library of controls and want to make deployment and use as easy as possible, it is essential that we keep everything contained in our assembly. To create our pop-up calendar window without having to deploy any extra files, in the "Creating the Calendar Pop-Up" section, we will create a new CrmDateTimeCalendar class that inherits from Page and add an HttpHandler to our web.config to serve the page.

The final table cell contains the HTML select box of time options. We only add this cell for CrmDateTime attributes the have the Format set to "Date and Time". The select options range from 12:00 A.M. to 11:30 P.M. and are formatted based on the user’s preferred time format.

Creating the Calendar Pop-Up

We use the ASP.NET calendar control in the calendar pop-up. First we add a new Class file to the Controls project.

Adding theCrmDateTimeCalendar class

  1. Right-click the ProgrammingWithDynamicsCrm4.Controls Project in Solution Explorer. Under Add, click New Item.

  2. In the Visual C# Items category, select the Class template.

  3. Type CrmDateTimeCalendar.cs in the Name box and click Add.

Because this is an actual page, we inherit the CrmDateTimeCalendar class from System.Web. UI.Page. We do not have an aspx file to work with, so we build our page’s control hierarchy in our newly added class file. Example 14-4 shows the source code for the CrmDateTimeCalendar class.

Example 14-4. CrmDateTimeCalendar source code

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace ProgrammingWithDynamicsCrm4.Controls
{
    public class CrmDateTimeCalendar : System.Web.UI.Page
    {
        protected override void OnInit(EventArgs e)
        {
            HtmlForm form = new HtmlForm();
            this.Controls.Add(form);

            // add the calendar control
            Calendar calendar = new Calendar();
            calendar.ID = "datepicker";
            calendar.Style.Add("width", "100%");
            calendar.Style.Add("height", "100%");
            calendar.SelectionChanged +=
                                        new EventHandler(Calendar_SelectionChanged);
            form.Controls.Add(calendar);

            // add a hidden input to store the date control's id
            HtmlInputHidden hdnDateControl = new HtmlInputHidden();
            hdnDateControl.ID = "datecontrol";
            hdnDateControl.Value = Request.QueryString["datecontrol"];

            form.Controls.Add(hdnDateControl);

            // add a hidden input to store the user's date format
            HtmlInputHidden hdnDateFormat = new HtmlInputHidden();
            hdnDateFormat.ID = "dateformat";
            hdnDateFormat.Value = Request.QueryString["dateformat"];
            form.Controls.Add(hdnDateFormat);

            base.OnInit(e);
        }

        protected void Calendar_SelectionChanged(object sender, EventArgs e)
        {
            HtmlForm form = this.Form;
            Calendar calendar = (Calendar)form.Controls[0];
            HtmlInputHidden hdnDateControl = (HtmlInputHidden)form.Controls[1];
            HtmlInputHidden hdnDateFormat = (HtmlInputHidden)form.Controls[2];

            StringBuilder updateScript = new StringBuilder();
            updateScript.Append("<script>");
            updateScript.AppendFormat("window.opener.document.all.{0}.value =
                               '{1}';",
                               hdnDateControl.Value,
                               calendar.SelectedDate.ToString(hdnDateFormat.Value));
            updateScript.Append("self.close();");
            updateScript.Append("</script>");

            ClientScript.RegisterClientScriptBlock(this.GetType(),
                                                  "updatescript",
                                                  updateScript.ToString());
        }
    }
}

We build the HTML form and controls for our pop-up page in the OnInit method of the CrmDateTimeCalendar class. First we create an ASP.NET Calendar control with the height and width set to 100% so that it will fill our entire window. The Calendar control also needs an EventHandler to handle when the user selects a date. Next we create two hidden HTML inputs to store the id of the date input from the CrmDateTimeControl and the user’s preferred date format string that are passed to the window in the query string. If you look back at Example 14-3, you will notice that our calendar button has an onclick event set to open a page named "CrmDateTimeCalendar.aspx" and it passes a value for the date control id and date format string in the query string.

calButton.Attributes.Add("onclick",
     String.Format(@"window.open('crmdatetimecalendar.aspx?datecontrol='
              + this.parentElement.previousSibling.firstChild.id
              + '&dateformat={0}','cal','width=250,height=225,left=270,top=180'),",
              dateFormat))

The Calendar_SelectionChanged method is called when the user makes a selection. This method gets an instance of all of the controls we created on this page and then adds a block of JavaScript that populates the date input on the pop-up window’s opener and then closes the calendar window.

Testing the CrmDateTimeControl

Adding theCrmDateTimeControl test page

  1. Open the ProgrammingWithDynamicsCrm4.Web project in Visual Studio.

  2. Right-click the project name in Solution Explorer, and click Add New Item.

  3. Select the Web Form template and type the name CrmDateTimeControlPage.aspx in the Name box. Click OK.

We need to make an addition to our web.config file to handle opening our calendar pop-up window. Under the system.web node add <httpHandlers ><add verb="*" path="crmdatetimecalendar.aspx" type="ProgrammingWithDynamicsCrm4.Controls. CrmDateTimeCalendar" /></httpHandlers>. When the request for the crmdatetimecalendar.aspx page comes in, this code will direct it to our CrmDateTimeCalendar class.

<httpHandlers >
    <add verb="*"
         path="crmdatetimecalendar.aspx"
         type="ProgrammingWithDynamicsCrm4.Controls.CrmDateTimeCalendar" />
</httpHandlers>

After we add the HttpHandler, we can add the CrmDateTimeControl to our page. Add <crm: CrmDateTimeControl ID="crmDateTimeControl" EntityName="lead" AttributeName ="estimatedclosedate" runat="server" /> to our page to test with the Lead’s estimated-closedate attribute. If you view this page in the browser, you can see the HTML input for date along with our calendar button. Clicking the button pops up our ASP.NET Calendar control and allows you to select a date (Figure 14-3).

<crm:CrmDateTimeControl ID="crmDateTimeControl"
                        EntityName="lead"
                        AttributeName="estimatedclosedate"
                        runat="server" />
CrmDateTimeControl

Figure 14-3. CrmDateTimeControl

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset