For example, in WinForms there are many events where you can call e.Cancel = true and then the execution of the event processing is completed.

How does it work, how does it work and how to implement such an event yourself?

    2 answers 2

    In .NET there is a standard class CancelEventArgs .

    If you need to pass some data to the handler, create a descendant from CancelEventArgs . If not, just use CancelEventArgs as is.

     class MyEventArgs : CancelEventArgs { } class SomeClass { public event EventHandler<MyEventArgs> SomeEvent; private bool OnSomeEvent() { var args = new MyEventArgs(); SomeEvent?.Invoke(this, args); return !args.Cancel; } public void SomeAction() { // наступило событие if (OnSomeEvent()) { // продолжить } else { // отменить } } } 

    If you use your own parameters for the event, it is not necessary to inherit from CancelEventArgs - you can simply add bool Cancel to the already existing data.

      1) (Optional) In some cases, if someone canceled an assignment, it is useful to throw an exception, thus informing the assignment code of the cancellation, although you can get by just checking the success of the assignment, or ignore the cancellation altogether. Exception class that I use.

       [Serializable] /// Исключение возникает при прерывании выполнения setter для свойства public class SetterAbortException : Exception { public SetterAbortException() { } public SetterAbortException(string message) : base(message) { } public SetterAbortException(string message, Exception inner) : base(message, inner) { } protected SetterAbortException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } 

      2) It will take a descendant class EventArgs containing a cancel flag and data proposed for assignment. If there is no suitable one in .Net, connected libraries or your solution, you will have to create it.

       public class ValueChangingEventArgs : EventArgs { public ValueChangingEventArgs(decimal newvalue) { Cancel = false; NewValue = newvalue; } public bool Cancel { get; set; } public decimal NewValue { get; private set; } } 

      3) Create an EventHandler corresponding to our EventArgs.

       public delegate void ValueChangingEventHandler(object sender, ValueChangingEventArgs ea); 

      4) It is desirable to implement a private / protected method for triggering an event.

        /// <summary> /// Вызов события о начале изменения значения /// </summary> /// <param name="value">новое значение</param> /// <returns>Разрешение продолжить значение</returns> protected virtual bool onValueChanging(decimal value) { var ea = new ValueChangingEventArgs(value); if (ValueChanging != null) { ValueChanging(this, ea); } return !ea.Cancel; } /// <summary> /// Событие возникает при начале изменения значения свойства Value /// </summary> public event ValueChangingEventHandler ValueChanging; 

      5) It remains to write a property with an exception throw, with or without cancellation.

        private decimal value; /// <summary> /// Значение параметра в единицах СИ /// </summary> public decimal Value { get { return value; } set { if (!this.value.Equals(value)) //Проверяем новое значение присваивается или нет. Проверку можно убрать, если нужно, чтобы событие срабатывало даже, когда присваивается старое значение. { if (onValueChanging(value)) { this.value = value; onValueChanged(); //Вызов события о завершении присвоения } else // Удалить если не нужно исключение throw new SetterAbortException ("Присвоение прервано"); } } } 
      • 2) Already have CancelEventArgs - andreycha
      • @andreycha, and this is also noted in the PashaPash answer ♦. However, it also says "If you use your parameters for the event, then it is not necessary to inherit from CancelEventArgs". An event whose handlers will know what is assigned to a property, and not just the fact of an attempted assignment, may be more useful for subscribers ... - 4per