¿Cómo puedo hacer mi propio evento en C #?

Respuestas:

217

Aquí hay un ejemplo de creación y uso de un evento con C #

using System;

namespace Event_Example
{
    //First we have to define a delegate that acts as a signature for the
    //function that is ultimately called when the event is triggered.
    //You will notice that the second parameter is of MyEventArgs type.
    //This object will contain information about the triggered event.
    public delegate void MyEventHandler(object source, MyEventArgs e);

    //This is a class which describes the event to the class that recieves it.
    //An EventArgs class must always derive from System.EventArgs.
    public class MyEventArgs : EventArgs
    {
        private string EventInfo;
        public MyEventArgs(string Text)
        {
            EventInfo = Text;
        }
        public string GetInfo()
        {
            return EventInfo;
        }
    }

    //This next class is the one which contains an event and triggers it
    //once an action is performed. For example, lets trigger this event
    //once a variable is incremented over a particular value. Notice the
    //event uses the MyEventHandler delegate to create a signature
    //for the called function.
    public class MyClass
    {
        public event MyEventHandler OnMaximum;
        private int i;
        private int Maximum = 10;
        public int MyValue
        {
            get
            {
                return i;
            }
            set
            {
                if(value <= Maximum)
                {
                    i = value;
                }
                else
                {
                    //To make sure we only trigger the event if a handler is present
                    //we check the event to make sure it's not null.
                    if(OnMaximum != null)
                    {
                        OnMaximum(this, new MyEventArgs("You've entered " +
                            value.ToString() +
                            ", but the maximum is " +
                            Maximum.ToString()));
                    }
                }
            }
        }
    }

    class Program
    {
        //This is the actual method that will be assigned to the event handler
        //within the above class. This is where we perform an action once the
        //event has been triggered.
        static void MaximumReached(object source, MyEventArgs e)
        {
            Console.WriteLine(e.GetInfo());
        }

        static void Main(string[] args)
        {
            //Now lets test the event contained in the above class.
            MyClass MyObject = new MyClass();
            MyObject.OnMaximum += new MyEventHandler(MaximumReached);

            for(int x = 0; x <= 15; x++)
            {
                MyObject.MyValue = x;
            }

            Console.ReadLine();
        }
    }
}
Gary Willoughby
fuente
44
Después de visitar cien explicaciones, esto finalmente me ayudó a entender. SE tenía razón, las publicaciones siguen siendo relevantes después de varios años.
1
{¡Meh!} Siempre me olvido de escribir en la eventparte de la clase.
jp2code
51

Tengo una discusión completa de eventos y delegados en mi artículo de eventos . Para el tipo de evento más simple, puede declarar un evento público y el compilador creará un evento y un campo para realizar un seguimiento de los suscriptores:

public event EventHandler Foo;

Si necesita una lógica de suscripción / cancelación de suscripción más complicada, puede hacerlo explícitamente:

public event EventHandler Foo
{
    add
    {
        // Subscription logic here
    }
    remove
    {
        // Unsubscription logic here
    }
}
Jon Skeet
fuente
1
No estaba seguro de cómo llamar al evento desde mi código, pero resulta ser realmente obvio. Simplemente lo llama como un método que le pasa un remitente y un objeto EventArgs. [es decir. if (fooHappened) Foo (remitente, eventArgs); ]
Richard Garside
2
@ Richard: No del todo; debe manejar el caso donde no hay suscriptores, por lo que la referencia de delegado será nula.
Jon Skeet
Esperamos la actualización de C # 4 sobre eventos seguros para subprocesos en el artículo que vinculó. Muy buen trabajo, @JonSkeet!
kdbanman
20

Puede declarar un evento con el siguiente código:

public event EventHandler MyOwnEvent;

Se puede usar un tipo de delegado personalizado en lugar de EventHandler si es necesario.

Puede encontrar información detallada / tutoriales sobre el uso de eventos en .NET en el artículo Tutorial de eventos (MSDN).

Brann
fuente
4

para hacerlo tenemos que conocer los tres componentes

  1. el lugar responsable de firing the Event
  2. el lugar responsable de responding to the Event
  3. el evento en sí

    a. Evento

    b .EventArgs

    C. Enumeración EventArgs

ahora vamos a crear un evento que se dispara cuando se llama a una función

pero mi orden de resolver este problema es la siguiente: estoy usando la clase antes de crearla

  1. el lugar responsable de responding to the Event

    NetLog.OnMessageFired += delegate(object o, MessageEventArgs args) 
    {
            // when the Event Happened I want to Update the UI
            // this is WPF Window (WPF Project)  
            this.Dispatcher.Invoke(() =>
            {
                LabelFileName.Content = args.ItemUri;
                LabelOperation.Content = args.Operation;
                LabelStatus.Content = args.Status;
            });
    };

NetLog es una clase estática. Lo explicaré más tarde.

el siguiente paso es

  1. el lugar responsable de firing the Event

    //this is the sender object, MessageEventArgs Is a class I want to create it  and Operation and Status are Event enums
    NetLog.FireMessage(this, new MessageEventArgs("File1.txt", Operation.Download, Status.Started));
    downloadFile = service.DownloadFile(item.Uri);
    NetLog.FireMessage(this, new MessageEventArgs("File1.txt", Operation.Download, Status.Finished));

el tercer paso

  1. el evento en sí

Deformé el evento dentro de una clase llamada NetLog

public sealed class NetLog
{
    public delegate void MessageEventHandler(object sender, MessageEventArgs args);

    public static event MessageEventHandler OnMessageFired;
    public static void FireMessage(Object obj,MessageEventArgs eventArgs)
    {
        if (OnMessageFired != null)
        {
            OnMessageFired(obj, eventArgs);
        }
    }
}

public class MessageEventArgs : EventArgs
{
    public string ItemUri { get; private set; }
    public Operation Operation { get; private set; }
    public Status Status { get; private set; }

    public MessageEventArgs(string itemUri, Operation operation, Status status)
    {
        ItemUri = itemUri;
        Operation = operation;
        Status = status;
    }
}

public enum Operation
{
    Upload,Download
}

public enum Status
{
    Started,Finished
}

esta clase contienen ahora the Event, EventArgsy EventArgs Enumsy the functionresponsable de desencadenar el evento

lo siento por esta larga respuesta

Basheer AL-MOMANI
fuente
La diferencia clave en esta respuesta es hacer que el evento sea estático, lo que permite recibir eventos sin requerir una referencia al objeto que activó el evento. Excelente para suscribirse a eventos desde múltiples controles independientes.
Radderz