/// <summary>
 /// Raises the HasBrokenRules event.
 /// </summary>
 /// <param name="e">Event arguments.</param>
 protected virtual void OnHasBrokenRules(HasBrokenRulesEventArgs e)
 {
     if (HasBrokenRules != null)
     {
         HasBrokenRules(this, e);
     }
 }
        /// <summary>
        /// Method invoked when the target control is clicked.
        /// </summary>
        /// <param name="sender">Object originating action.</param>
        /// <param name="e">Arguments.</param>
        protected void OnClick(object sender, System.EventArgs e)
        {
            Control ctl = (Control)sender;
            YYTActionExtenderProperties props = _Sources[ctl] as YYTActionExtenderProperties;

            if (props.ActionType != YYTFormAction.None)
            {
                try
                {
                    bool raiseClicked             = true;
                    YYTActionCancelEventArgs args = new YYTActionCancelEventArgs(false, props.CommandName);
                    OnClicking(args);
                    if (!args.Cancel)
                    {
                        // perform action
                        YYT.Core.ISavable     savableObject   = null;
                        YYT.Core.ITrackStatus trackableObject = null;

                        BindingSource source = null;
                        if (_dataSource != null)
                        {
                            source = _dataSource as BindingSource;

                            if (source != null)
                            {
                                savableObject   = source.DataSource as YYT.Core.ISavable;
                                trackableObject = source.DataSource as YYT.Core.ITrackStatus;
                            }
                            else
                            {
                                OnErrorEncountered(new ErrorEncounteredEventArgs(
                                                       props.CommandName, new InvalidCastException(STR_InvalidBindingSourceCast)));
                            }

                            if (savableObject == null || trackableObject == null)
                            {
                                OnErrorEncountered(new ErrorEncounteredEventArgs(
                                                       props.CommandName, new InvalidCastException(STR_InvalidBusinessObjectBaseCast)));
                            }
                        }

                        DialogResult diagResult;

                        switch (props.ActionType)
                        {
                        case YYTFormAction.Save:

                            bool okToContinue = true;

                            if (savableObject is YYT.Core.BusinessBase)
                            {
                                YYT.Core.BusinessBase businessObject = savableObject as YYT.Core.BusinessBase;
                                if (businessObject.BrokenRulesCollection.Count > 0)
                                {
                                    HasBrokenRulesEventArgs argsHasBrokenRules = new HasBrokenRulesEventArgs(
                                        props.CommandName,
                                        businessObject.BrokenRulesCollection.ErrorCount > 0,
                                        businessObject.BrokenRulesCollection.WarningCount > 0,
                                        businessObject.BrokenRulesCollection.InformationCount > 0,
                                        _autoShowBrokenRules);

                                    OnHasBrokenRules(argsHasBrokenRules);

                                    okToContinue = !argsHasBrokenRules.Cancel;
                                    //in case the client changed it
                                    _autoShowBrokenRules = argsHasBrokenRules.AutoShowBrokenRules;
                                }
                            }

                            if (okToContinue)
                            {
                                if (savableObject is YYT.Core.BusinessBase)
                                {
                                    YYT.Core.BusinessBase businessObject = savableObject as YYT.Core.BusinessBase;
                                    if (_autoShowBrokenRules && businessObject.BrokenRulesCollection.Count > 0)
                                    {
                                        MessageBox.Show(businessObject.BrokenRulesCollection.ToString());
                                    }
                                }

                                bool objectValid = trackableObject.IsValid;

                                if (objectValid)
                                {
                                    YYTActionCancelEventArgs savingArgs = new YYTActionCancelEventArgs(
                                        false, props.CommandName);
                                    OnObjectSaving(savingArgs);

                                    if (!args.Cancel)
                                    {
                                        _bindingSourceTree.Apply();

                                        //save
                                        YYT.Core.ISavable objectToSave = savableObject;

                                        if (YYT.ApplicationContext.AutoCloneOnUpdate)
                                        {
                                            objectToSave = ((ICloneable)savableObject).Clone() as YYT.Core.ISavable;
                                        }

                                        if (objectToSave != null)
                                        {
                                            YYT.Core.ISavable saveableObject = objectToSave as YYT.Core.ISavable;

                                            try
                                            {
                                                savableObject = savableObject.Save() as YYT.Core.ISavable;

                                                OnObjectSaved(new YYTActionEventArgs(props.CommandName));

                                                switch (props.PostSaveAction)
                                                {
                                                case PostSaveActionType.None:

                                                    if (source != null && props.RebindAfterSave)
                                                    {
                                                        _bindingSourceTree.Bind(savableObject);
                                                    }

                                                    break;

                                                case PostSaveActionType.AndClose:

                                                    CloseForm();
                                                    break;

                                                case PostSaveActionType.AndNew:

                                                    OnSetForNew(new YYTActionEventArgs(props.CommandName));
                                                    break;
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                OnErrorEncountered(new ErrorEncounteredEventArgs(props.CommandName, new ObjectSaveException(ex)));
                                                raiseClicked = false;
                                            }
                                        }
                                        else
                                        {
                                            // did not find bound object so don't bother raising the Clicked event
                                            raiseClicked = false;
                                        }

                                        _bindingSourceTree.SetEvents(true);
                                    }
                                }
                                else
                                {
                                    OnBusinessObjectInvalid(new YYTActionEventArgs(props.CommandName));
                                    // object not valid or has broken rules set to invalidate it due to this control's properties
                                    raiseClicked = false;
                                }
                            }
                            else
                            {
                                // process was canceled from the HasBrokenRules event
                                raiseClicked = false;
                            }

                            break;

                        case YYTFormAction.Cancel:

                            diagResult = System.Windows.Forms.DialogResult.Yes;
                            if (_warnOnCancel && trackableObject.IsDirty)
                            {
                                diagResult = MessageBox.Show(
                                    _warnOnCancelMessage, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                            }

                            if (diagResult == System.Windows.Forms.DialogResult.Yes)
                            {
                                _bindingSourceTree.Cancel(savableObject);
                            }

                            break;

                        case YYTFormAction.Close:

                            diagResult = System.Windows.Forms.DialogResult.Yes;
                            if (trackableObject.IsDirty || trackableObject.IsNew)
                            {
                                if (_warnIfCloseOnDirty)
                                {
                                    diagResult = MessageBox.Show(
                                        _dirtyWarningMessage + Environment.NewLine + STR_CloseConfirmation, "Warning",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                                }
                            }

                            if (diagResult == System.Windows.Forms.DialogResult.Yes)
                            {
                                _bindingSourceTree.Close();
                                _closeForm = true;
                            }

                            break;
                        }

                        if (raiseClicked)
                        {
                            if (props.ActionType == YYTFormAction.Save && source != null && props.RebindAfterSave)
                            {
                                // For some strange reason, this has to be done down here.
                                // Putting it in the Select Case AfterSave... does not work.
                                _bindingSourceTree.ResetBindings(false);
                                InitializeControls(true);
                            }

                            OnClicked(new YYTActionEventArgs(props.CommandName));
                        }
                    }

                    if (_closeForm)
                    {
                        CloseForm();
                    }
                }
                catch (Exception ex)
                {
                    OnErrorEncountered(new ErrorEncounteredEventArgs(props.CommandName, ex));
                }
            }
        }