/// <summary>
        /// Handles the Delete event of the gMarketingCampaignAdType control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gMarketingCampaignAdType_Delete( object sender, RowEventArgs e )
        {
            RockTransactionScope.WrapTransaction( () =>
            {
                MarketingCampaignAdTypeService marketingCampaignAdTypeService = new MarketingCampaignAdTypeService();
                MarketingCampaignAdType marketingCampaignAdType = marketingCampaignAdTypeService.Get( (int)e.RowKeyValue );

                if ( marketingCampaignAdType != null )
                {
                    string errorMessage;
                    if ( !marketingCampaignAdTypeService.CanDelete( marketingCampaignAdType, out errorMessage ) )
                    {
                        mdGridWarning.Show( errorMessage, ModalAlertType.Information );
                        return;
                    }

                    marketingCampaignAdTypeService.Delete( marketingCampaignAdType, CurrentPersonId );
                    marketingCampaignAdTypeService.Save( marketingCampaignAdType, CurrentPersonId );
                }
            } );

            BindGrid();
        }
        /// <summary>
        /// Handles the Delete event of the gMarketingCampaignAdType control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gMarketingCampaignAdType_Delete( object sender, RowEventArgs e )
        {
            MarketingCampaignAdTypeService marketingCampaignAdTypeService = new MarketingCampaignAdTypeService();
            int marketingCampaignAdTypeId = (int)e.RowKeyValue;
            MarketingCampaignAdType marketingCampaignAdType = marketingCampaignAdTypeService.Get( marketingCampaignAdTypeId );

            string errorMessage;
            if ( !marketingCampaignAdTypeService.CanDelete( marketingCampaignAdType, out errorMessage ) )
            {
                mdGridWarning.Show( errorMessage, ModalAlertType.Information );
                return;
            }

            if ( CurrentBlock != null )
            {
                marketingCampaignAdTypeService.Delete( marketingCampaignAdType, CurrentPersonId );
                marketingCampaignAdTypeService.Save( marketingCampaignAdType, CurrentPersonId );
            }

            BindGrid();
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            using ( new UnitOfWorkScope() )
            {
                MarketingCampaignAdType marketingCampaignAdType;
                MarketingCampaignAdTypeService marketingCampaignAdTypeService = new MarketingCampaignAdTypeService();

                int marketingCampaignAdTypeId = int.Parse( hfMarketingCampaignAdTypeId.Value );

                if ( marketingCampaignAdTypeId == 0 )
                {
                    marketingCampaignAdType = new MarketingCampaignAdType();
                    marketingCampaignAdTypeService.Add( marketingCampaignAdType, CurrentPersonId );
                }
                else
                {
                    marketingCampaignAdType = marketingCampaignAdTypeService.Get( marketingCampaignAdTypeId );
                }

                marketingCampaignAdType.Name = tbName.Text;
                marketingCampaignAdType.DateRangeType = (DateRangeTypeEnum)int.Parse( ddlDateRangeType.SelectedValue );

                if ( !marketingCampaignAdType.IsValid )
                {
                    // Controls will render the error messages                    
                    return;
                }

                RockTransactionScope.WrapTransaction( () =>
                {
                    AttributeService attributeService = new AttributeService();
                    AttributeQualifierService attributeQualifierService = new AttributeQualifierService();
                    CategoryService categoryService = new CategoryService();

                    marketingCampaignAdTypeService.Save( marketingCampaignAdType, CurrentPersonId );

                    // get it back to make sure we have a good Id for it for the Attributes
                    marketingCampaignAdType = marketingCampaignAdTypeService.Get( marketingCampaignAdType.Guid );

                    var entityTypeId = EntityTypeCache.Read(typeof(MarketingCampaignAd)).Id;
                    string qualifierColumn = "MarketingCampaignAdTypeId";
                    string qualifierValue = marketingCampaignAdType.Id.ToString();

                    // Get the existing attributes for this entity type and qualifier value
                    var attributes = attributeService.Get( entityTypeId, qualifierColumn, qualifierValue );

                    // Delete any of those attributes that were removed in the UI
                    var selectedAttributeGuids = AttributesState.Select( a => a.Guid );
                    foreach ( var attr in attributes.Where( a => !selectedAttributeGuids.Contains( a.Guid ) ) )
                    {
                        Rock.Web.Cache.AttributeCache.Flush( attr.Id );

                        attributeService.Delete( attr, CurrentPersonId );
                        attributeService.Save( attr, CurrentPersonId );
                    }

                    // Update the Attributes that were assigned in the UI
                    foreach ( var attributeState in AttributesState )
                    {
                        Rock.Attribute.Helper.SaveAttributeEdits( attributeState, attributeService, attributeQualifierService, categoryService,
                            entityTypeId, qualifierColumn, qualifierValue, CurrentPersonId );
                    }
                } );
            }

            NavigateToParentPage();
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            MarketingCampaignAdType marketingCampaignAdType;
            MarketingCampaignAdTypeService marketingCampaignAdTypeService = new MarketingCampaignAdTypeService();

            int marketingCampaignAdTypeId = int.Parse( hfMarketingCampaignAdTypeId.Value );

            if ( marketingCampaignAdTypeId == 0 )
            {
                marketingCampaignAdType = new MarketingCampaignAdType();
                marketingCampaignAdTypeService.Add( marketingCampaignAdType, CurrentPersonId );
            }
            else
            {
                marketingCampaignAdType = marketingCampaignAdTypeService.Get( marketingCampaignAdTypeId );
            }

            marketingCampaignAdType.Name = tbName.Text;
            marketingCampaignAdType.DateRangeType = (DateRangeTypeEnum)int.Parse( ddlDateRangeType.SelectedValue );

            // check for duplicates
            if ( marketingCampaignAdTypeService.Queryable().Count( a => a.Name.Equals( marketingCampaignAdType.Name, StringComparison.OrdinalIgnoreCase ) && !a.Id.Equals( marketingCampaignAdType.Id ) ) > 0 )
            {
                tbName.ShowErrorMessage( WarningMessage.DuplicateFoundMessage( "name", MarketingCampaignAdType.FriendlyTypeName ) );
                return;
            }

            if ( !marketingCampaignAdType.IsValid )
            {
                // Controls will render the error messages
                return;
            }

            RockTransactionScope.WrapTransaction( () =>
            {
                marketingCampaignAdTypeService.Save( marketingCampaignAdType, CurrentPersonId );

                // get it back to make sure we have a good Id for it for the Attributes
                marketingCampaignAdType = marketingCampaignAdTypeService.Get( marketingCampaignAdType.Guid );

                // delete AdTypeAttributes that are no longer configured in the UI
                AttributeService attributeService = new AttributeService();
                var qry = attributeService.GetByEntityTypeId( new MarketingCampaignAd().TypeId ).AsQueryable()
                    .Where( a => a.EntityTypeQualifierColumn.Equals( "MarketingCampaignAdTypeId", StringComparison.OrdinalIgnoreCase )
                    && a.EntityTypeQualifierValue.Equals( marketingCampaignAdType.Id.ToString() ) );

                var deletedAttributes = from attr in qry
                                        where !( from d in AttributesState
                                                 select d.Guid ).Contains( attr.Guid )
                                        select attr;

                deletedAttributes.ToList().ForEach( a =>
                    {
                        var attr = attributeService.Get( a.Guid );
                        attributeService.Delete( attr, CurrentPersonId );
                        attributeService.Save( attr, CurrentPersonId );
                    } );

                // add/update the AdTypes that are assigned in the UI
                foreach ( var attributeState in AttributesState )
                {
                    Attribute attribute = qry.FirstOrDefault( a => a.Guid.Equals( attributeState.Guid ) );
                    if ( attribute == null )
                    {
                        attribute = attributeState.ToModel();
                        attributeService.Add( attribute, CurrentPersonId );
                    }
                    else
                    {
                        attributeState.Id = attribute.Id;
                        attributeState.CopyToModel( attribute );
                    }

                    attribute.EntityTypeQualifierColumn = "MarketingCampaignAdTypeId";
                    attribute.EntityTypeQualifierValue = marketingCampaignAdType.Id.ToString();
                    attribute.EntityTypeId = Rock.Web.Cache.EntityTypeCache.Read( new MarketingCampaignAd().TypeName ).Id;
                    attributeService.Save( attribute, CurrentPersonId );
                }
            } );

            BindGrid();
            pnlDetails.Visible = false;
            pnlList.Visible = true;
        }