4

I'm having some trouble with figuring out a way of unsubscribing from some anonymous delegate events that i found in a pre-made helper file that helps allow movement of controls at run time. The reason i want to unsubscribe to these events is so that the control (in this case buttons) will become locked again and not able to be moved. Here is the method in the helper class:

 public static void Init(Control control)
    {
        Init(control, Direction.Any);
    }

    public static void Init(Control control, Direction direction)
    {
        Init(control, control, direction);
    }

 public static void Init(Control control, Control container, Direction direction)
    {
        bool Dragging = false;
        Point DragStart = Point.Empty;

        control.MouseDown += delegate(object sender, MouseEventArgs e)
        {
            Dragging = true;
            DragStart = new Point(e.X, e.Y);
            control.Capture = true;
        };
        control.MouseUp += delegate(object sender, MouseEventArgs e)
        {
            Dragging = false;
            control.Capture = false;
        };
        control.MouseMove += delegate(object sender, MouseEventArgs e)
        {
            if (Dragging)
            {
                if (direction != Direction.Vertical)
                    container.Left = Math.Max(0, e.X + container.Left - DragStart.X);
                if (direction != Direction.Horizontal)
                    container.Top = Math.Max(0, e.Y + container.Top - DragStart.Y);
            }
        };

    }

and here's how i subscribe to these events by calling the method;

    ControlMover.Init(this.Controls["btn" + i]);

I've read about some methods on MSDN about unsubscribing to these by creating a local variable holding these events and then unsubscribing through this way, but i can't seem to get this working in my own project. How do i go about unsubscribing to these events so that my controls become fixed in position again?

Kestami
  • 2,045
  • 3
  • 32
  • 47
  • Can you post your code, where you store them in a variable and use that to unsubscribe? – CodesInChaos Jun 07 '12 at 13:59
  • 1
    But personally I'd use named methods for this. Easier, and cleaner code IMO. – CodesInChaos Jun 07 '12 at 14:00
  • i've removed this since as i couldn't get anything to even remotely work. i'll try and retrieve some or further work on it, but it wasn't looking good! – Kestami Jun 07 '12 at 14:00
  • You would need to name your delegate to unsubscribe. Following discussions should help: http://stackoverflow.com/questions/1362204/c-how-to-remove-a-lambda-event-handler http://stackoverflow.com/questions/2051357/c-sharp-adding-and-removing-anonymous-event-handler – S2S2 Jun 07 '12 at 14:07

2 Answers2

9

Anonymous delegates are not guaranteed to be unique as created by the compiler, when unsubscribing this lack of uniqueness of the same code will cause it to fail to unsubscribe the correct handler. The only way to do so safely is to keep a reference to the delegate and use that to unsubscribe, or change it to a full method.

Delegates are equal based on object instance and method signature I believe.

A possible duplicate:

How to remove a lambda event handler

Basically, keep a reference:

MouseEventHandler handler = (sender, e) =>
        {
            Dragging = true;
            DragStart = new Point(e.X, e.Y);
            control.Capture = true;
        };

control.MouseDown += handler;
control.MouseDown -= handler;

Or turn the anonymous method into a proper method.

Community
  • 1
  • 1
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • cheers for your input. I think for the sake of making things easier in the long run i'll just turn them into proper methods. – Kestami Jun 07 '12 at 14:11
  • @Shane'Shamus'Coulter I would, it will also make your registration code a little cleaner: `control.MouseDown += MouseDownHandler;` – Adam Houldsworth Jun 07 '12 at 14:12
  • So it turns out i'm actually quite struggling with making them proper methods due to all the passing about of parameters in the class.. – Kestami Jun 07 '12 at 15:38
  • In that case, either make those parameters class member variables, or make the anonymous method references class members. – Adam Houldsworth Jun 07 '12 at 15:40
  • is it possible to unsubscribe from: control.MouseDown += new MouseEventHandler((sender, e) => MouseDown(sender, e, control)); ? or is this the same thing..i have a feeling it is.. – Kestami Jun 07 '12 at 16:09
  • The lambda expression is the same as I explain in my answer, I'm not sure if old style delegates have the same issue, I presume they do. – Adam Houldsworth Jun 07 '12 at 16:25
  • looks like im'a have to do some rearrangement and make these into proper methods. failing that i'll scratch the class and just make my own new one. *sigh* – Kestami Jun 07 '12 at 16:33
1

In short, you can not do that with anonymous delegate.

If you want to have a abbilty to unsubscribe from the event, define a delegate/action and follow a pattern you refer.

Tigran
  • 61,654
  • 8
  • 86
  • 123