CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
CslaActionExtenderToolStrip.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="CslaActionExtenderToolStrip.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Extender control providing automation around</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Collections.Generic;
10using System.ComponentModel;
11using System.Windows.Forms;
12using Csla.Core;
14using Csla.Properties;
15
16namespace Csla.Windows
17{
22 [ToolboxItem(true)]
23 [ProvideProperty("ActionType", typeof (ToolStripButton))]
24 [ProvideProperty("PostSaveAction", typeof (ToolStripButton))]
25 [ProvideProperty("RebindAfterSave", typeof (ToolStripButton))]
26 [ProvideProperty("DisableWhenClean", typeof (ToolStripButton))]
27 [ProvideProperty("DisableWhenUseless", typeof (ToolStripButton))]
28 [ProvideProperty("CommandName", typeof (ToolStripButton))]
29 public class CslaActionExtenderToolStrip : Component, IExtenderProvider
30 {
31 #region Constructors
32
37 public CslaActionExtenderToolStrip(IContainer container)
38 {
39 _container = container;
40 container.Add(this);
41 }
42
43 #endregion
44
45 #region Member variables
46
47 private Dictionary<ToolStripButton, CslaActionExtenderProperties> _sources =
48 new Dictionary<ToolStripButton, CslaActionExtenderProperties>();
49
50 private object _dataSource = null;
51 private bool _autoShowBrokenRules = true;
52 private bool _warnIfCloseOnDirty = true;
53 private string _dirtyWarningMessage = Resources.ActionExtenderDirtyWarningMessagePropertyDefault;
54 private bool _warnOnCancel = false;
55 private string _warnOnCancelMessage = Resources.ActionExtenderWarnOnCancelMessagePropertyDefault;
56 private string _objectIsValidMessage = Resources.ActionExtenderObjectIsValidMessagePropertyDefault;
57 private IContainer _container = null;
58 private BindingSourceNode _bindingSourceTree = null;
59 private bool _closeForm = false;
60
61 #endregion
62
63 #region IExtenderProvider implementation
64
65 bool IExtenderProvider.CanExtend(object extendee)
66 {
67 return extendee is ToolStripButton;
68 }
69
70 #endregion
71
72 #region Public properties
73
77 [Category("Data")]
78 [Description("Gets or sets the data source to which this button is bound for action purposes.")]
79 [AttributeProvider(typeof (IListSource))]
80 public object DataSource
81 {
82 get { return _dataSource; }
83 set
84 {
85 if (value != null)
86 {
87 if (value is BindingSource)
88 _dataSource = value;
89 else
90 throw new ArgumentException(Resources.ActionExtenderSourceMustBeBindingSource);
91 }
92 }
93 }
94
99 [Category("Behavior")]
100 [Description("If True, then the broken rules will be displayed in a message box, should the object be invalid.")]
101 [Bindable(true)]
102 [DefaultValue(true)]
104 {
105 get { return _autoShowBrokenRules; }
106 set { _autoShowBrokenRules = value; }
107 }
108
113 [Category("Behavior")]
114 [Description("If True, then the control (when set to Close mode) will warn the user if the object is currently dirty.")]
115 [Bindable(true)]
116 [DefaultValue(true)]
118 {
119 get { return _warnIfCloseOnDirty; }
120 set { _warnIfCloseOnDirty = value; }
121 }
122
127 [Category("Behavior")]
128 [Description("Gets or sets the confirmation message that will display if a Close button is pressed and the object is dirty.")]
129 [Bindable(true)]
130 [DefaultValue("Object is currently in a dirty changed.")]
131 [Localizable(true)]
133 {
134 get { return _dirtyWarningMessage; }
135 set { _dirtyWarningMessage = value; }
136 }
137
142 [Category("Behavior")]
143 [Description("If True, then the Cancel button will warn when pressed and the object is dirty.")]
144 [Bindable(true)]
145 [DefaultValue(false)]
146 public bool WarnOnCancel
147 {
148 get { return _warnOnCancel; }
149 set { _warnOnCancel = value; }
150 }
151
156 [Category("Behavior")]
157 [Description("If the WarnOnCancel property is set to True, this is the message to be displayed.")]
158 [Bindable(true)]
159 [DefaultValue("Are you sure you want to revert to the previous values?")]
160 [Localizable(true)]
162 {
163 get { return _warnOnCancelMessage; }
164 set { _warnOnCancelMessage = value; }
165 }
166
171 [Category("Behavior")]
172 [Description("When a button with a Validate ActionType is pressed when the object is valid, this is the message to be displayed.")]
173 [Bindable(true)]
174 [DefaultValue("Object is valid.")]
175 [Localizable(true)]
177 {
178 get { return _objectIsValidMessage; }
179 set { _objectIsValidMessage = value; }
180 }
181
182 #endregion
183
184 #region Property accessor methods
185
186 #region ActionType
187
193 [Category("Csla")]
194 [Description("Gets or sets the action type for this button.")]
195 [Bindable(true)]
196 [DefaultValue(CslaFormAction.None)]
197 public CslaFormAction GetActionType(ToolStripButton ctl)
198 {
199 if (_sources.ContainsKey(ctl))
200 return _sources[ctl].ActionType;
201
202 return CslaActionExtenderProperties.ActionTypeDefault;
203 }
204
210 [Category("Csla")]
211 [Description("Gets or sets the action type for this button.")]
212 [Bindable(true)]
213 [DefaultValue(CslaFormAction.None)]
214 public void SetActionType(ToolStripButton ctl, CslaFormAction value)
215 {
216 if (_sources.ContainsKey(ctl))
217 _sources[ctl].ActionType = value;
218 else
219 {
220 CslaActionExtenderProperties props = new CslaActionExtenderProperties();
221 props.ActionType = value;
222 _sources.Add(ctl, props);
223 }
224 }
225
226 #endregion
227
228 #region PostSaveAction
229
235 [Category("Csla")]
236 [Description("Gets or sets the action performed after a save (if ActionType is set to Save).")]
237 [Bindable(true)]
238 [DefaultValue(PostSaveActionType.None)]
239 public PostSaveActionType GetPostSaveAction(ToolStripButton ctl)
240 {
241 if (_sources.ContainsKey(ctl))
242 return _sources[ctl].PostSaveAction;
243
244 return CslaActionExtenderProperties.PostSaveActionDefault;
245 }
246
252 [Category("Csla")]
253 [Description("Gets or sets the action performed after a save (if ActionType is set to Save).")]
254 [Bindable(true)]
255 [DefaultValue(PostSaveActionType.None)]
256 public void SetPostSaveAction(ToolStripButton ctl, PostSaveActionType value)
257 {
258 if (_sources.ContainsKey(ctl))
259 _sources[ctl].PostSaveAction = value;
260 else
261 {
262 CslaActionExtenderProperties props = new CslaActionExtenderProperties();
263 props.PostSaveAction = value;
264 _sources.Add(ctl, props);
265 }
266 }
267
268 #endregion
269
270 #region RebindAfterSave
271
276 [Category("Csla")]
277 [Description("Determines if the binding source will rebind after business object saves.")]
278 [Bindable(true)]
279 [DefaultValue(true)]
280 public bool GetRebindAfterSave(ToolStripButton ctl)
281 {
282 if (_sources.ContainsKey(ctl))
283 return _sources[ctl].RebindAfterSave;
284
285 return CslaActionExtenderProperties.RebindAfterSaveDefault;
286 }
287
293 [Category("Csla")]
294 [Description("Determines if the binding source will rebind after business object saves.")]
295 [Bindable(true)]
296 [DefaultValue(true)]
297 public void SetRebindAfterSave(ToolStripButton ctl, bool value)
298 {
299 if (_sources.ContainsKey(ctl))
300 _sources[ctl].RebindAfterSave = value;
301 else
302 {
303 CslaActionExtenderProperties props = new CslaActionExtenderProperties();
304 props.RebindAfterSave = value;
305 _sources.Add(ctl, props);
306 }
307 }
308
309 #endregion
310
311 #region DisableWhenUseless
312
317 [Category("Csla")]
318 [Description("If True, then the status of the underlying business object will cause this button to be enabled or disabled.")]
319 [Bindable(true)]
320 [DefaultValue(false)]
321 public bool GetDisableWhenUseless(ToolStripButton ctl)
322 {
323 if (_sources.ContainsKey(ctl))
324 return _sources[ctl].DisableWhenUseless;
325
326 return CslaActionExtenderProperties.DisableWhenUselessDefault;
327 }
328
334 [Category("Csla")]
335 [Description("If True, then the status of the underlying business object will cause this button to be enabled or disabled.")]
336 [Bindable(true)]
337 [DefaultValue(true)]
338 public void SetDisableWhenUseless(ToolStripButton ctl, bool value)
339 {
340 if (_sources.ContainsKey(ctl))
341 _sources[ctl].DisableWhenUseless = value;
342 else
343 {
344 CslaActionExtenderProperties props = new CslaActionExtenderProperties();
345 props.DisableWhenUseless = value;
346 _sources.Add(ctl, props);
347 }
348 }
349
350 #endregion
351
352 #region CommandName
353
358 [Category("Csla")]
359 [Description("Gets or sets the name of this command control for unique identification purposes.")]
360 [Bindable(true)]
361 [DefaultValue("")]
362 public string GetCommandName(ToolStripButton ctl)
363 {
364 if (_sources.ContainsKey(ctl))
365 return _sources[ctl].CommandName;
366
367 return CslaActionExtenderProperties.CommandNameDefault;
368 }
369
375 [Category("Csla")]
376 [Description("Gets or sets the name of this command control for unique identification purposes.")]
377 [Bindable(true)]
378 [DefaultValue("")]
379 public void SetCommandName(ToolStripButton ctl, string value)
380 {
381 if (_sources.ContainsKey(ctl))
382 _sources[ctl].CommandName = value;
383 else
384 {
385 CslaActionExtenderProperties props = new CslaActionExtenderProperties();
386 props.CommandName = value;
387 _sources.Add(ctl, props);
388 }
389 }
390
391 #endregion
392
393 #endregion
394
395 #region Event declarations
396
400 [Category("Csla")]
401 [Description("Event fires just before the attempted action.")]
402 public event EventHandler<CslaActionCancelEventArgs> Clicking;
403
407 [Category("Csla")]
408 [Description("Event fires after a successful action. When button is set to Save, this event will only fire upon a successful save. If button is set to Close, this event will never fire.")]
409 public event EventHandler<CslaActionEventArgs> Clicked;
410
414 [Category("Csla")]
415 [Description("Event fires upon encountering any exception during an action.")]
416 public event EventHandler<ErrorEncounteredEventArgs> ErrorEncountered;
417
421 [Category("Csla")]
422 [Description("Event fires upon a successful save when the PostSaveAction property is set to AndNew.")]
423 public event EventHandler<CslaActionEventArgs> SetForNew;
424
428 [Category("Csla")]
429 [Description("Event fires when the object is in an invalid state. Note that this event will work in conjunction with the InvalidateOnWarnings and InvalidateOnInformation properties.")]
430 public event EventHandler<CslaActionEventArgs> BusinessObjectInvalid;
431
435 [Category("Csla")]
436 [Description("Event fires if there are any broken rules at all, despite severity.")]
437 public event EventHandler<HasBrokenRulesEventArgs> HasBrokenRules;
438
442 [Category("Csla")]
443 [Description("Fires just before a save action is performed.")]
444 public event EventHandler<CslaActionCancelEventArgs> ObjectSaving;
445
449 [Category("Csla")]
450 [Description("Fires immediately after the underlying object successfully saves.")]
451 public event EventHandler<CslaActionEventArgs> ObjectSaved;
452
453 #endregion
454
455 #region OnEvent methods
456
461 protected virtual void OnClicking(CslaActionCancelEventArgs e)
462 {
463 if (Clicking != null)
464 Clicking(this, e);
465 }
466
471 protected virtual void OnClicked(CslaActionEventArgs e)
472 {
473 if (Clicked != null)
474 Clicked(this, e);
475 }
476
482 {
483 if (ErrorEncountered != null)
484 ErrorEncountered(this, e);
485 }
486
491 protected virtual void OnSetForNew(CslaActionEventArgs e)
492 {
493 if (SetForNew != null)
494 SetForNew(this, e);
495 }
496
502 {
503 if (BusinessObjectInvalid != null)
504 BusinessObjectInvalid(this, e);
505 }
506
512 {
513 if (HasBrokenRules != null)
514 HasBrokenRules(this, e);
515 }
516
522 {
523 if (ObjectSaving != null)
524 ObjectSaving(this, e);
525 }
526
531 protected virtual void OnObjectSaved(CslaActionEventArgs e)
532 {
533 if (ObjectSaved != null)
534 ObjectSaved(this, e);
535 }
536
537 #endregion
538
539 #region Public methods
540
545 public void ResetActionBehaviors(ISavable objectToBind)
546 {
547 InitializeControls(true);
548
549 BindingSource rootSource = _dataSource as BindingSource;
550
551 if (rootSource != null)
552 {
553 AddEventHooks(objectToBind);
554 }
555
556 _bindingSourceTree = BindingSourceHelper.InitializeBindingSourceTree(_container, rootSource);
557 _bindingSourceTree.Bind(objectToBind);
558 }
559
560 private void AddEventHooks(ISavable objectToBind)
561 {
562 // make sure to not attach many times
563 RemoveEventHooks(objectToBind);
564
565 INotifyPropertyChanged propChangedObjParent = objectToBind as INotifyPropertyChanged;
566 if (propChangedObjParent != null)
567 {
568 propChangedObjParent.PropertyChanged += propChangedObj_PropertyChanged;
569 }
570
571 INotifyChildChanged propChangedObjChild = objectToBind as INotifyChildChanged;
572 if (propChangedObjChild != null)
573 {
574 propChangedObjChild.ChildChanged += propChangedObj_ChildChanged;
575 }
576 }
577
578 private void RemoveEventHooks(ISavable objectToBind)
579 {
580 INotifyPropertyChanged propChangedObjParent = objectToBind as INotifyPropertyChanged;
581 if (propChangedObjParent != null)
582 {
583 propChangedObjParent.PropertyChanged -= propChangedObj_PropertyChanged;
584 }
585
586 INotifyChildChanged propChangedObjChild = objectToBind as INotifyChildChanged;
587 if (propChangedObjChild != null)
588 {
589 propChangedObjChild.ChildChanged -= propChangedObj_ChildChanged;
590 }
591 }
592
593 private void propChangedObj_ChildChanged(object sender, ChildChangedEventArgs e)
594 {
595 ResetControls();
596 }
597
598 private void propChangedObj_PropertyChanged(object sender, PropertyChangedEventArgs e)
599 {
600 ResetControls();
601 }
602
603 #endregion
604
605 #region Protected methods
606
612 protected void OnClick(object sender, EventArgs e)
613 {
614 ToolStripButton ctl = (ToolStripButton) sender;
615 CslaActionExtenderProperties props = _sources[ctl];
616 if (props.ActionType != CslaFormAction.None)
617 {
618 try
619 {
620 bool raiseClicked = true;
621 CslaActionCancelEventArgs args = new CslaActionCancelEventArgs(false, props.CommandName);
622 OnClicking(args);
623 if (!args.Cancel)
624 {
625 ISavable savableObject = null;
626 ITrackStatus trackableObject = null;
627 BindingSource source = null;
628
629 var sourceObjectError = false;
630 if (_dataSource != null)
631 {
632 source = _dataSource as BindingSource;
633
634 if (source != null)
635 {
636 savableObject = source.DataSource as ISavable;
637 trackableObject = source.DataSource as ITrackStatus;
638 }
639 else
640 {
641 OnErrorEncountered(new ErrorEncounteredEventArgs(props.CommandName, new InvalidCastException(Resources.ActionExtenderInvalidBindingSourceCast)));
642 sourceObjectError = true;
643 }
644
645 if (savableObject == null || trackableObject == null)
646 {
648 sourceObjectError = true;
649 }
650 }
651
652 if (!sourceObjectError)
653 {
654 DialogResult diagResult;
655
656 switch (props.ActionType)
657 {
658 case CslaFormAction.Save:
659 raiseClicked = ExecuteSaveAction(savableObject, trackableObject, props);
660 break;
661 // case CslaFormAction.Save
662
663 case CslaFormAction.Cancel:
664
665 diagResult = DialogResult.Yes;
666 if (_warnOnCancel && trackableObject.IsDirty)
667 diagResult = MessageBox.Show(
668 _warnOnCancelMessage, Resources.Warning,
669 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
670
671 if (diagResult == DialogResult.Yes)
672 _bindingSourceTree.Cancel(savableObject);
673
674 break;
675 // case CslaFormAction.Cancel
676
677 case CslaFormAction.Close:
678
679 diagResult = DialogResult.Yes;
680 if (trackableObject.IsDirty || trackableObject.IsNew)
681 {
682 if (_warnIfCloseOnDirty)
683 diagResult = MessageBox.Show(
684 _dirtyWarningMessage + Environment.NewLine + Resources.ActionExtenderCloseConfirmation,
685 Resources.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
686 }
687
688 if (diagResult == DialogResult.Yes)
689 {
690 _bindingSourceTree.Close();
691 _closeForm = true;
692 }
693
694 break;
695 // case CslaFormAction.Close
696
697 case CslaFormAction.Validate:
698
699 if (savableObject is BusinessBase)
700 {
701 BusinessBase businessObject = savableObject as BusinessBase;
702 if (!businessObject.IsValid)
703 {
704 string brokenRules = string.Empty;
705 foreach (var brokenRule in businessObject.GetBrokenRules())
706 {
707 var lambdaBrokenRule = brokenRule;
708 var friendlyName =
709 PropertyInfoManager.GetRegisteredProperties(businessObject.GetType()).Find(
710 c => c.Name == lambdaBrokenRule.Property).FriendlyName;
711 brokenRules += string.Format("{0}: {1}{2}", friendlyName, brokenRule, Environment.NewLine);
712 }
713 MessageBox.Show(brokenRules, Resources.ActionExtenderErrorCaption,
714 MessageBoxButtons.OK, MessageBoxIcon.Error);
715 }
716 else
717 {
718 MessageBox.Show(_objectIsValidMessage, Resources.ActionExtenderInformationCaption,
719 MessageBoxButtons.OK, MessageBoxIcon.Information);
720 }
721 }
722
723 break;
724 //case CslaFormAction.Validate
725
726 } // switch (props.ActionType)
727
728 // raiseClicked is true if
729 // ActionType == CslaFormAction.Save and everything is ok
730 if (raiseClicked)
731 {
732 if (props.ActionType == CslaFormAction.Save && source != null)
733 {
734 if (props.RebindAfterSave)
735 {
736 // For some strange reason, this has to be done down here.
737 // Putting it in the Select Case AfterSave... does not work.
738 _bindingSourceTree.ResetBindings(false);
739 InitializeControls(true);
740 }
741 }
742 else
743 {
744 if (props.ActionType == CslaFormAction.Cancel)
745 InitializeControls(true);
746 }
747
748 OnClicked(new CslaActionEventArgs(props.CommandName));
749 }
750
751 } // if (!sourceObjectError)
752
753 } // if (!args.Cancel)
754
755 if (_closeForm)
756 CloseForm();
757 }
758 catch (Exception ex)
759 {
760 OnErrorEncountered(new ErrorEncounteredEventArgs(props.CommandName, ex));
761 }
762 } // if (props.ActionType != CslaFormAction.None)
763 }
764
765 #endregion
766
767 #region Private methods
768
769 private bool ExecuteSaveAction(ISavable savableObject, ITrackStatus trackableObject, CslaActionExtenderProperties props)
770 {
771 var result = true;
772 bool okToContinue = true;
773
774 BusinessBase businessObject = null;
775 bool savableObjectIsBusinessBase = savableObject is BusinessBase;
776 if (savableObjectIsBusinessBase)
777 businessObject = savableObject as BusinessBase;
778
779 if (savableObjectIsBusinessBase)
780 {
781 if (!businessObject.IsValid)
782 {
783 HasBrokenRulesEventArgs argsHasBrokenRules = new HasBrokenRulesEventArgs(
784 props.CommandName,
785 businessObject.GetBrokenRules().ErrorCount > 0,
786 businessObject.GetBrokenRules().WarningCount > 0,
787 businessObject.GetBrokenRules().InformationCount > 0,
788 _autoShowBrokenRules);
789
790 OnHasBrokenRules(argsHasBrokenRules);
791
792 okToContinue = !argsHasBrokenRules.Cancel;
793 //in case the client changed it
794 _autoShowBrokenRules = argsHasBrokenRules.AutoShowBrokenRules;
795 }
796 }
797
798 if (okToContinue)
799 {
800 if (savableObjectIsBusinessBase)
801 {
802 if (_autoShowBrokenRules && !businessObject.IsValid)
803 {
804 string brokenRules = string.Empty;
805 foreach (var brokenRule in businessObject.GetBrokenRules())
806 {
807 var lambdaBrokenRule = brokenRule;
808 var friendlyName =
809 PropertyInfoManager.GetRegisteredProperties(businessObject.GetType()).Find(
810 c => c.Name == lambdaBrokenRule.Property).FriendlyName;
811 brokenRules += string.Format("{0}: {1}{2}", friendlyName, brokenRule, Environment.NewLine);
812 }
813 MessageBox.Show(brokenRules, Resources.ActionExtenderErrorCaption,
814 MessageBoxButtons.OK, MessageBoxIcon.Error);
815 }
816 }
817
818 if (trackableObject.IsValid)
819 {
820 CslaActionCancelEventArgs savingArgs = new CslaActionCancelEventArgs(false, props.CommandName);
821 OnObjectSaving(savingArgs);
822
823 if (!savingArgs.Cancel)
824 {
825 _bindingSourceTree.Apply();
826 ISavable objectToSave;
827
829 objectToSave = ((ICloneable)savableObject).Clone() as ISavable;// if not AutoClone, clone manually
830 else
831 objectToSave = savableObject;
832
833 if (objectToSave != null)
834 {
835 try
836 {
837 RemoveEventHooks(savableObject);
838 savableObject = savableObject.Save() as ISavable;
839
840 OnObjectSaved(new CslaActionEventArgs(props.CommandName));
841
842 switch (props.PostSaveAction)
843 {
844 case PostSaveActionType.None:
845
846 if (props.RebindAfterSave)
847 {
848 _bindingSourceTree.Bind(savableObject);
849 AddEventHooks(savableObject);
850 }
851 break;
852
853 case PostSaveActionType.AndClose:
854
855 CloseForm();
856 break;
857
858 case PostSaveActionType.AndNew:
859
860 OnSetForNew(new CslaActionEventArgs(props.CommandName));
861 AddEventHooks(savableObject);
862 break;
863 }
864 }
865 catch (Exception ex)
866 {
867 _bindingSourceTree.Bind(objectToSave);
868 AddEventHooks(objectToSave);
869 OnErrorEncountered(new ErrorEncounteredEventArgs(props.CommandName, new ObjectSaveException(ex)));
870 // there was some problem
871 result = false;
872 }
873 }
874 else
875 {
876 // did not find bound object so don't bother raising the Clicked event
877 result = false;
878 }
879
880 _bindingSourceTree.SetEvents(true);
881 }
882 }
883 else
884 {
885 OnBusinessObjectInvalid(new CslaActionEventArgs(props.CommandName));
886 // object not valid or has broken rules set to invalidate it due to this control's properties
887 result = false;
888 }
889 }
890 else
891 {
892 // process was canceled from the HasBrokenRules event (okToContinue = false)
893 result = false;
894 }
895
896 return result;
897 }
898
899 private void ResetControls()
900 {
901 InitializeControls(false);
902 }
903
904 private void InitializeControls(bool initialEnabling)
905 {
906 // controls will not be enabled until the BusinessObjectPropertyChanged event fires or if it's in an appropriate state now
907 List<ToolStripButton> extendedControls = new List<ToolStripButton>();
908 foreach (KeyValuePair<ToolStripButton, CslaActionExtenderProperties> pair in _sources)
909 {
910 if (pair.Value.ActionType != CslaFormAction.None)
911 {
912 ToolStripButton ctl = pair.Key;
913 if (initialEnabling)
914 {
915 if (pair.Value.DisableWhenUseless || pair.Value.DisableWhenClean)
916 ChangeEnabled(ctl, !(pair.Value.DisableWhenUseless || pair.Value.DisableWhenClean));
917 pair.Key.Click -= OnClick;
918 pair.Key.Click += OnClick;
919 }
920 InitializeControl(ctl, pair);
921 extendedControls.Add(ctl);
922 }
923 }
924 }
925
926 private void InitializeControl(ToolStripButton ctl, KeyValuePair<ToolStripButton, CslaActionExtenderProperties> pair)
927 {
928 if (pair.Value.DisableWhenUseless || (pair.Value.DisableWhenClean && !ctl.Enabled))
929 {
930 ISavable businessObject = GetBusinessObject();
931 if (businessObject != null)
932 {
933 ITrackStatus trackableObject = businessObject as ITrackStatus;
934 if (trackableObject != null)
935 {
936 if (pair.Value.ActionType == CslaFormAction.Cancel || pair.Value.DisableWhenClean)
937 ChangeEnabled(ctl, trackableObject.IsNew || trackableObject.IsDirty || trackableObject.IsDeleted);
938 if (pair.Value.ActionType == CslaFormAction.Save)
939 ChangeEnabled(ctl, (trackableObject.IsNew || trackableObject.IsDirty || trackableObject.IsDeleted)
940 && trackableObject.IsValid);
941 }
942 }
943 }
944 }
945
946 private void ChangeEnabled(ToolStripButton ctl, bool newEnabled)
947 {
948 // only do this if it's changed to avoid flicker
949 if (ctl.Enabled != newEnabled)
950 ctl.Enabled = newEnabled;
951 }
952
953 private void CloseForm()
954 {
955 if (_sources.Count > 0)
956 {
957 Dictionary<ToolStripButton, CslaActionExtenderProperties>.Enumerator enumerator = _sources.GetEnumerator();
958 if (enumerator.MoveNext())
959 {
960 ToolStripButton ctl = enumerator.Current.Key;
961 Form frm = GetParentForm(ctl);
962 if (frm != null)
963 frm.Close();
964 }
965 }
966 }
967
968 private Form GetParentForm(ToolStripButton thisToolStripButton)
969 {
970 return GetParentForm(thisToolStripButton.GetCurrentParent());
971 }
972
973 private Form GetParentForm(Control thisControl)
974 {
975 Form frm;
976
977 if (thisControl.Parent is Form)
978 frm = (Form) thisControl.Parent;
979 else
980 frm = GetParentForm(thisControl.Parent);
981
982 return frm;
983 }
984
985 private ISavable GetBusinessObject()
986 {
987 ISavable businessObject = null;
988 BindingSource source = _dataSource as BindingSource;
989 if (source != null)
990 businessObject = source.DataSource as ISavable;
991
992 return businessObject;
993 }
994
995 #endregion
996 }
997}
Provides consistent context information between the client and server DataPortal objects.
static bool AutoCloneOnUpdate
Gets a value indicating whether objects should be automatically cloned by the data portal Update() me...
This is the base class from which most business objects will be derived.
Definition: BusinessBase.cs:38
virtual bool IsValid
Returns true if the object and its child objects are currently valid, false if the object or any of i...
BrokenRulesCollection GetBrokenRules()
Gets the broken rules for this object
Contains event data about the changed child object.
A strongly-typed resource class, for looking up localized strings, etc.
static string ActionExtenderInvalidBindingSourceCast
Looks up a localized string similar to DataSource does not cast to a BindingSource.
static string ActionExtenderErrorCaption
Looks up a localized string similar to Error.
static string ActionExtenderSourceMustBeBindingSource
Looks up a localized string similar to DataSource must be a BindingSource control instance.
static string ActionExtenderWarnOnCancelMessagePropertyDefault
Looks up a localized string similar to Are you sure you want to revert to the previous values?...
static string ActionExtenderCloseConfirmation
Looks up a localized string similar to Are you sure you want to close?.
static string ActionExtenderObjectIsValidMessagePropertyDefault
Looks up a localized string similar to Object is valid.
static string Warning
Looks up a localized string similar to Warning.
static string ActionExtenderInformationCaption
Looks up a localized string similar to Information.
static string ActionExtenderDirtyWarningMessagePropertyDefault
Looks up a localized string similar to Object is currently in a dirty changed.
static string ActionExtenderInvalidBusinessObjectBaseCast
Looks up a localized string similar to The underlying data source does not cast to a CSLA BusinessBas...
Maintains a reference to a BindingSource object on the form.
void Close()
Disconnects from the BindingSource object.
void Apply()
Applies changes to the business object.
void Cancel(object businessObject)
Cancels changes to the business object.
void Bind(object objectToBind)
Binds a business object to the BindingSource.
Event args providing information about a canceled action.
Extender control (for ToolStripButton only) providing automation around data binding to CSLA ....
virtual void OnObjectSaving(CslaActionCancelEventArgs e)
Raises the ObjectSaving event.
PostSaveActionType GetPostSaveAction(ToolStripButton ctl)
Gets the post save action.
EventHandler< CslaActionEventArgs > ObjectSaved
Event indicating that the object has been saved.
virtual void OnHasBrokenRules(HasBrokenRulesEventArgs e)
Raises the HasBrokenRules event.
EventHandler< CslaActionEventArgs > Clicked
Event indicating the user clicked on the ToolStripButton.
EventHandler< HasBrokenRulesEventArgs > HasBrokenRules
Event indicating the business object has broken rules.
void OnClick(object sender, EventArgs e)
Method invoked when the target control is clicked.
void SetRebindAfterSave(ToolStripButton ctl, bool value)
Sets the rebind after save value.
virtual void OnErrorEncountered(ErrorEncounteredEventArgs e)
Raises the ErrorEncountered event.
bool WarnIfCloseOnDirty
Gets or sets a value indicating whether to warn the user on close when the object is dirty.
EventHandler< ErrorEncounteredEventArgs > ErrorEncountered
Event indicating an error was encountered.
void SetActionType(ToolStripButton ctl, CslaFormAction value)
Sets the action type.
string ObjectIsValidMessage
Gets or sets the message shown to the user when a button with a Validate ActionType is pressed when t...
CslaActionExtenderToolStrip(IContainer container)
Creates an instance of the type.
void ResetActionBehaviors(ISavable objectToBind)
Resets all action behaviors.
CslaFormAction GetActionType(ToolStripButton ctl)
Gets the action type.
void SetPostSaveAction(ToolStripButton ctl, PostSaveActionType value)
Sets the post save action.
string DirtyWarningMessage
Gets or sets the message shown to the user in a close on dirty warning.
virtual void OnObjectSaved(CslaActionEventArgs e)
Raises the ObjectSaved event.
EventHandler< CslaActionEventArgs > SetForNew
Event indicating the object is set for new.
bool AutoShowBrokenRules
Gets or sets a value indicating whether to automatically show broken rules.
string WarnOnCancelMessage
Gets or sets the message shown to the user in a warn on cancel.
bool GetDisableWhenUseless(ToolStripButton ctl)
Gets the disable when useless value.
virtual void OnClicking(CslaActionCancelEventArgs e)
Raises the Clicking event.
virtual void OnBusinessObjectInvalid(CslaActionEventArgs e)
Raises the BusinessObjectInvalid event.
bool WarnOnCancel
Gets or sets a value indicating whether to warn the user on cancel.
void SetDisableWhenUseless(ToolStripButton ctl, bool value)
Sets the disable when useless value.
object DataSource
Gets or sets a reference to the data source object.
EventHandler< CslaActionCancelEventArgs > ObjectSaving
Event indicating that the object is saving.
virtual void OnClicked(CslaActionEventArgs e)
Raises the Clicked event.
bool GetRebindAfterSave(ToolStripButton ctl)
Gets the rebind after save value.
EventHandler< CslaActionEventArgs > BusinessObjectInvalid
Event indicating the business object is in an invalid state.
string GetCommandName(ToolStripButton ctl)
Gets the command name value.
EventHandler< CslaActionCancelEventArgs > Clicking
Event indicating the user is clicking on the ToolStripButton.
virtual void OnSetForNew(CslaActionEventArgs e)
Raises the SetForNew event.
void SetCommandName(ToolStripButton ctl, string value)
Sets the command name value.
Event args object containing information about a broken rule.
bool AutoShowBrokenRules
Gets a value indicating whether to show broken rules.
Implemented by classes that notify when a child object has changed.
EventHandler< ChildChangedEventArgs > ChildChanged
Event indictating that a child object has changed.
Specifies that the object can save itself.
Definition: ISavableT.cs:19
object Save()
Saves the object to the database.
Defines the common properties required objects that track their own status.
Definition: ITrackStatus.cs:17
bool IsDeleted
Returns true if this object is marked for deletion.
bool IsNew
Returns true if this is a new object, false if it is a pre-existing object.
bool IsValid
Returns true if the object and its child objects are currently valid, false if the object or any of i...
Definition: ITrackStatus.cs:37
bool IsDirty
Returns true if this object's data, or any of its fields or child objects data, has been changed.
Definition: ITrackStatus.cs:73
CslaFormAction
The possible form actions.
Definition: Enums.cs:14
PostSaveActionType
The possible actions for post save.
Definition: Enums.cs:41