A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://gammasoft71.github.io/xtd/docs/documentation/guides/xtd.core/types_overview/events below:

Events | xtd

Events In This Section Overview

Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers. In a typical xtd Windows Forms application, you subscribe to events raised by controls such as buttons and list boxes. For more information, see How to subscribe to and unsubscribe from events.

Events have the following properties:

How to subscribe to and unsubscribe from events To subscribe to events programmatically
  1. Define an event handler method whose signature matches the delegate signature for the event. For example, if the event is based on the xtd::event_handler delegate type, the following code represents the method stub:
void handle_custom_event(object& sender, custom_event_args& e) {  

}
  1. Use the addition assignment operator += to attach an event handler to the event. In the following example, assume that an object named publisher has an event named raise_custom_event. Note that the subscriber class needs a reference to the publisher class in order to subscribe to its events
publisher.raise_custom_event += {*this, &subscriber::handle_custom_event};

or

publisher.raise_custom_event += custom_event_handler(*this, &my_class::handle_custom_event);
To subscribe to events by using a lambda expression

If you don't have to unsubscribe from an event later, you can use the addition assignment operator += to attach a lambda expression as an event handler. In the following example, assume that an object named publisher has an event named *raise_custom_event and that a custom_event_args class has also been defined to carry some kind of specialized event information. Note that the subscriber class needs a reference to publisher in order to subscribe to its events.

publisher.raise_custom_event += [](object& sender, custom_event_args& e) {  
xtd::string s = sender.to_string() + " " + e.to_string();
console::write_line(s);
};

You cannot easily unsubscribe from an event if you used a lambda expression to subscribe to it. To unsubscribe in this scenario, go back to the code where you subscribe to the event, store the anonymous function in a delegate variable, and then add the delegate to the event. We recommend that you don't use lambda expression to subscribe to events if you have to unsubscribe from the event at some later point in your code. For more information about anonymous functions, see lambda expression.

Unsubscribing

To prevent your event handler from being invoked when the event is raised, unsubscribe from the event. In order to prevent crash, you should unsubscribe from events before you destroy a subscriber object. Until you unsubscribe from an event, the multicast delegate that underlies the event in the publishing object has a reference to the delegate that encapsulates the subscriber's event handler.

To unsubscribe from an event

Use the subtraction assignment operator -= to unsubscribe from an event:

publisher.raise_custom_event -= {*this, &subscriber::handle_custom_event};

or

publisher.raise_custom_event -= custom_event_handler(*this, &subscriber::handle_custom_event);

When all subscribers have unsubscribed from an event, the event instance in the publisher class is set to empty.

How to publish events that conform to xtd Guidelines

The following procedure demonstrates how to add events that follow the standard xtd pattern to your classes and structs. All events in the xtd framework are based on the xtd::event_handler delegate, which is defined as follows:

template<typename event_args_t = const xtd::event_args&>
using generic_event_handler = xtd::delegate<void(xtd::object& sender, event_args_t e)>;

and

using event_handler = xtd::generic_event_handler<>;

Although events in classes that you define can be based on any valid delegate type, even delegates that return a value, it is generally recommended that you base your events on the xtd pattern by using xtd::event_handler, as shown in the following example. The name event_handler can lead to a bit of confusion as it doesn't actually handle the event. The xtd::event_handler, and generic xtd::generic_event_handler<event_args_t> are delegate types. A method or lambda expression whose signature matches the delegate definition is the event handler and will be invoked when the event is raised.

Publish events based on the event_handler pattern
  1. (Skip this step and go to Step 3a if you do not have to send custom data with your event.) Declare the class for your custom data at a scope that is visible to both your publisher and subscriber classes. Then add the required members to hold your custom event data. In this example, a simple string is returned.
struct custom_event_args : xtd::event_args {
custom_event_args() = default;
custom_event_args(const xtd::string& message) : message_(message) {}

xtd::string message;
};
  1. (Skip this step if you are using the generic version generic_event_handler<event_args_t>.) Declare a delegate in your publishing class. Give it a name that ends with event_handler. The second parameter specifies your custom event_args type.
using custom_event_handler = xtd::delegate<void(xtd::object& sender, custom_event_args& args)>;
  1. Declare the event in your publishing class by using one of the following steps.

a. If you have no custom event_args class, your event type will be the non-generic event_handler delegate. You do not have to declare the delegate because it is already declared in the xtd namespace that is included when you create your xtd project. Add the following code to your publisher class.

xtd::event<publisher, xtd::event_handler> raise_custom_event;

where publisher is the class name that contains the raise_custom_event event.

b. If you are using the non-generic version of event_handler and you have a custom class derived from event_args, declare your event inside your publishing class and use your delegate from step 2 as the type.

xtd::event<publisher, custom_event_handler> raise_custom_event;

Where publisher is the class name that contains the raise_custom_event event.

c. If you are using the generic version, you do not need a custom delegate. Instead, in your publishing class, you specify your event type as generic_event_handler<custom_event_args>, substituting the name of your own class between the angle brackets.

xtd::event<publisher, generic_event_handler<custom_event_args&>> raise_custom_event;

Where publisher is the class name that contains the raise_custom_event event.

Example

The following example demonstrates the previous steps by using a custom event_args class and genric_event_handler<event_args_t> as the event type.

#include <xtd/xtd>

using namespace xtd;


struct custom_event_args : xtd::event_args {
custom_event_args() = default;
custom_event_args(const xtd::string& message) : message_(message) {}

xtd::string message;
};


class publisher : public object {
public:

event<publisher, generic_event_handler<custom_event_args&>> raise_custom_event;

void do_something() {



custom_event_args event_args("Event triggered");
on_raise_custom_event(event_args);
}

protected:


virtual void on_raise_custom_event(custom_event_args& e) {



event<publisher, generic_event_handler<custom_event_args&>> raise_event = raise_custom_event;


if (!raise_event.is_empty()) {

e.message(string::format("{} at {}", e.message(), date_time::now()));


raise_event(*this, e);
}
}
};


class subscriber : public object {
public:
subscriber(string id, publisher& pub) : id_(id) {

pub.raise_custom_event += {*this, &subscriber::handle_custom_event};
}


void handle_custom_event(object& sender, custom_event_args& e) {
console::write_line(string::format("{} received this message: {}", id_, e.message()));
}

private:
string id_;
};

class program {
public:
static auto main() {
publisher pub;
subscriber sub1("sub1", pub);
subscriber sub2("sub2", pub);


pub.do_something();
}
};

startup_(program::main);
See also

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4