/// <summary>
        /// Activate the FAILED Alternate Keys
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolButtonActivate_Click(object sender, EventArgs e)
        {
            // get the selected item from the list
            var items          = ListViewKeyList.SelectedItems;
            var failedKeys     = new List <EntityKeyMetadata>();
            var approveMessage = new StringBuilder();

            foreach (ListViewItem item in items)
            {
                var key = item.Tag as EntityKeyMetadata;
                if (key.EntityKeyIndexStatus == EntityKeyIndexStatus.Failed)
                {
                    var keyName = CrmActions.GetLocalizedLabel(key.DisplayName, key.SchemaName);
                    failedKeys.Add(key);
                    approveMessage.AppendLine($"{keyName}");
                }
            }

            if (failedKeys.Count == 0)
            {
                MessageBox.Show(this, $"No Failed Keys Selected. Activate is only supported for Failed Entity Keys", "No Failed Keys Selected", MessageBoxButtons.OK);
            }
            else
            {
                if (MessageBox.Show(this, $"Activate the following keys?\n{approveMessage.ToString()}", "Reactivate Key?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    ReactivateKeys(failedKeys);
                }
            }
        }
        /// <summary>
        /// Delete selected Keys
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolButtonDelete_Click(object sender, EventArgs e)
        {
            // get the selected item from the list
            var items          = ListViewKeyList.SelectedItems;
            var approveMessage = new StringBuilder();
            var keys           = new List <EntityKeyMetadata>();

            foreach (ListViewItem item in items)
            {
                var key     = item.Tag as EntityKeyMetadata;
                var keyName = CrmActions.GetLocalizedLabel(key.DisplayName, key.SchemaName);
                keys.Add(key);
                approveMessage.AppendLine($"\t{keyName}");
            }

            var message = $"Are you sure you would like to delete Alternate Key(s)?\n{approveMessage.ToString()}?" +
                          $"\nNOTE: This cannot be undone!";

            if (MessageBox.Show(this, message, "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                CrmActions.DeleteEntityKey(Service, keys);

                LoadSelectedEntityKeys();
            }
        }
        /// <summary>
        /// Load the list of attributes that are allowed to be included as keys
        /// </summary>
        /// <param name="entity"></param>
        private void PopulateEntityAttributes(EntityMetadata entity)
        {
            // save the entity reference so we can do some validation.
            listBoxAttrbutes.Tag = entity;

            listBoxAttrbutes.Items.Clear();
            listBoxAttrbutes.DisplayMember = "Name";

            var attributes = entity.Attributes.ToList();

            if (attributes != null)
            {
                // only allowed certain types:
                // https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/define-alternate-keys-entity
                var allowed = attributes.Where(a =>
                                               (a is DecimalAttributeMetadata) ||
                                               (a is IntegerAttributeMetadata) ||
                                               (a is StringAttributeMetadata)
                                               // || (a is DateTimeAttributeMetadata) // these will be available in v9.1
                                               // || (a is LookupAttributeMetadata)
                                               // ||(a is PicklistAttributeMetadata)
                                               );

                // add the items to the checked list
                foreach (var attrib in allowed)
                {
                    if ((attrib.AttributeOf == null) && (attrib.AttributeType != AttributeTypeCode.Virtual))
                    {
                        listBoxAttrbutes.Items.Add(new AttributeListItem()
                        {
                            Name       = $"{CrmActions.GetLocalizedLabel(attrib.DisplayName, attrib.SchemaName)} ({attrib.SchemaName})",
                            SchemaName = attrib.SchemaName
                        });
                    }
                }
            }

            // reenable
            ToggleNewKeyPaneEnabled(true);

            ValidateNewKeyInputs(true);
        }
        /// <summary>
        /// Populate the Key Details pane controls with the Key Info
        /// </summary>
        /// <param name="key"></param>
        private void UpdateKeyDetailsPane(EntityKeyMetadata key)
        {
            labelKeyLogicalNameValue.Text = null;
            labelKeyIsManagedValue.Text   = null;
            labelKeyMetadataIdValue.Text  = null;
            labelKeySchemaNameValue.Text  = null;
            labelKeyNameValue.Text        = null;
            labelKeyStatusValue.Text      = null;
            labelScheduledJobValue.Text   = null;

            if (key != null)
            {
                labelKeyNameValue.Text        = CrmActions.GetLocalizedLabel(key.DisplayName, key.SchemaName);
                labelKeyLogicalNameValue.Text = key.LogicalName;
                labelKeySchemaNameValue.Text  = key.SchemaName;
                labelKeyStatusValue.Text      = key.EntityKeyIndexStatus.ToString();
                labelKeyIsManagedValue.Text   = key.IsManaged.Value.ToString();
                labelKeyMetadataIdValue.Text  = key.MetadataId.Value.ToString("b");
                labelScheduledJobValue.Text   = (key.AsyncJob != null) ? ((EntityReference)key.AsyncJob).Name :  null;
            }
        }