Mouse events and a ban on the execution of the method more than once?

All kind time of day!
Write your own GUI for a toy.
Class Button.
You have the following set of events delegates:
public event EventHandler MouseUpHandler;
public event EventHandler MouseDownHandler;
public event EventHandler MouseOutHandler;
public event EventHandler MouseInHandler;

Each event has a corresponding method:
private void OnMouseIn() {...}
private void OnMouseOut() {...}
private void OnMouseUp() {...}
private void OnMouseDown() {...}

In running the code like this:
private void OnMouseDown()
{
 EventHandler tempHandler = MouseDownHandler; // get the event delegate
 if (tempHandler != null) // check if not empty if the delegate
{
 tempHandler(this, EventArgs.Empty); // call the event
}
 _state = ButtonState.Click; // used to determine the correct coordinates on the sprite texture button when you have drawn it
}

The corresponding methods are present for other events-delegates.
In the same class has a method Update(), which calculates the logic of the code:
public void Update()
{
 /* Generated data about the mouse position and the area of intersection (based on the position and size of a button) */
 MouseState mouseState = Mouse.GetState();
 Point mousePosition = new Point(mouseState.X, mouseState.Y); 

 ButtonRectangle Rectangle = new Rectangle
(
 (int) this.Position.X, (int) this.Position.Y
 (int) this.Size.X, (int) this.Size.Y
);

 if (buttonRectangle.Contains(mousePosition)) // check to see if it intersects the mouse cursor and buttons
{
 if (mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed) //LKM - click
{
OnMouseDown();
}
 if (_mousePrevState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released) // LKM - mouse button is released
{
OnMouseUp();
}
 } else // output cursor off the button
{
OnMouseOut();
}
 _mousePrevState = mouseState; // save previous state (MouseUp may only be after a MouseDown)
}

In another place creates a button instance:
Button button = new Button(...);
Accordingly, by setting properties, textures, etc. All of this works.
Next, in "another place," delegate is assigned a method:
button.MouseInHandler += Navaneeta;
With this, I think, all should be clear.
Logic in a nutshell an object is created, it is a special delegate is assigned a method, then the method Update()checks whether the intersection of button and the cursor was a click, etc. and on this basis is called the desired event.
The problem that exists now:the method is invoked not once but many times in a row: in the absence of the mouse over the button repeatedly invoked the event OnMouseOut(), hover - OnMouseIn(), when you press and release the button corresponding events.
All this leads to the fact that, for example, the output to the console whatever text occurs multiple times, but requires no more than one.
I tried to solve the problem with additional fields:
private bool _isMouseUp;
private bool _isMouseDown;
private bool _isMouseIn;
private bool _isMouseOut;

A change in the structure of the logic of methods-events:
private void OnMouseIn()
{
 if (!_isMouseIn) // if the event was not called 
{
 EventHandler tempHandler = MouseInHandler;
 if (tempHandler != null)
{
 tempHandler(this, EventArgs.Empty);
}
 _isMouseIn = true; // define an event as caused and not let it occur again
 _isMouseOut = false; // after In the event you can prevent the execution of Out event
}
 _state = ButtonState.Hover;
}
// about the same code below except that now Out and In reversed
private void OnMouseOut()
{
 if (!_isMouseOut)
{
 EventHandler tempHandler = MouseOutHandler;
 if (tempHandler != null)
{
 tempHandler(this, EventArgs.Empty);
}
 _isMouseOut = true;
 _isMouseIn = false;
}
 _state = ButtonState.Normal;
}

For MouseDown and MouseUp appropriate changes.
And it works, as long as the user behaves normally. However, if you try different situations, for example, hold down the LMB, then hover over the button and release, or hold down the LMB over the button and release it at another place - all this leads to the fact that in any moment an event that was supposed to be called - not called or not called then the event that shall not be called.
I tried as much detail as possible to describe your problem, but if you have any questions - ask, clarify, if needed.
July 2nd 19 at 18:45
1 answer
July 2nd 19 at 18:47
Put Braco in the place where you sign up for the event
button.MouseInHandler += Navaneeta;
and see how many times it happens.
This is a common situation when in one context to an event, signed up, and forgot to unsubscribe and therefore the invocation list of the event handlers is stuffed with unnecessary.
I sign the event only once when initialize the button. I.e., logically, if I unsubscribe from the event in Update() then null will be eternal.
Or I something not so understood? - gustave_Ha commented on July 2nd 19 at 18:50
: just try with Bracey. Bring Braco to the handler of the opening event, could you have it where separate from the Risa event cause
I.e., logically, if I unsubscribe from the event in Update() then null will be eternal.
Or I something not so understood?

conceptually you understood everything correctly. If the handlers in the invocation list of the event remains the event = null.

And by the way, I understand the Button class you have in-house?
If Yes, then see if there are places where potentially, for the lifetime of the object button, these events can go to multiple subscriptions! - Sarai.Rutherford53 commented on July 2nd 19 at 18:53
: UPD: check out how many times the Update method is invoked in your case (well, respectively, and calls the handlers in this method). - Sarai.Rutherford53 commented on July 2nd 19 at 18:56
: Clarified a bit about the structure when: pastebin.com/W33nvSZb
The point is that the subscription at the moment, is done only once, in the constructor of the class MainMenu, there's also initializes all the other elements. This is quite convenient, as I can see this very clear: I'm just asking the method that should be called and not worry about it anymore. - gustave_Ha commented on July 2nd 19 at 18:59

Find more questions by tags MouseC#Programming