-2

I have a method which adds a click-event to a Button at Runtime.

     ((Button)ControlDictionary[processDataProperty.Key]).Click += (s, e) => { Process.Start(processDataProperty.Value.ToString()); };

The process opens a page in a browser. The problem is that, executing this code several times, I get the undesired effect of a multiple opening tags.

I tried this but it does not work.

     ((Button)ControlDictionary[processDataProperty.Key]).Click -= (s, e) => { Process.Start(processDataProperty.Value.ToString()); };
     ((Button)ControlDictionary[processDataProperty.Key]).Click += (s, e) => { Process.Start(processDataProperty.Value.ToString()); };

I need a method that checks if I can add the method but I was not able to find a solution.

I tried also How to remove a lambda event handler with no good results.

overcomer
  • 2,244
  • 3
  • 26
  • 39
  • So you want a single browser tab to open and then nothing to happen? – Alex Jan 10 '18 at 13:54
  • 3
    Possible duplicate of [How to remove a lambda event handler](https://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler) – Sinatr Jan 10 '18 at 13:55
  • @Sinatr I tried the solution of https://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler but it does not work – overcomer Jan 10 '18 at 14:15
  • 1
    You did it wrong. That first `-=` won't unsubscribe anything, because it's not the instance you have subscribed earlier. Just create a new method (event handler), subscribe/unsubscribe it to event, not lambdas. – Sinatr Jan 10 '18 at 14:31
  • 2
    Rather than calling a method to add a click handler to a button multiple times and writing it such that it only actually adds the handler once, you should instead write it such that it only actually gets called once. Then you don't need to remove the previous handler. – Servy Jan 10 '18 at 14:48

2 Answers2

0

The suggestions in the comments really should work but added events dynamically can be dangerous for the reason that you stated. Could you have the button click permanently wired to a method that uses a variable you change based on something else? Like:

ButtonClick(sender, args)
{
   var myTarget = TargetList[sender.Name];
   Process.Start(myTarget);
}
Echostorm
  • 9,678
  • 8
  • 36
  • 50
0

you need to ensure that subscription (+=) happens only once. It should happen when button is added to the ControlDictionary.

If that is not possible for some reason, I suggest to use Button.Command as equivalent to handling Click event. Button.Command can have only one value, so it will be executed once.

var button = (Button)ControlDictionary[processDataProperty.Key];
var cmd = new RelayCommand(() =>
{
     try
     {
         Process.Start(processDataProperty.Value.ToString());
     }
     catch (Exception ex)
     {
          Log.Debug(ex);
     }
});
button.Command = cmd;

RelayCommand is a custom implementation of ICommand. There are alternative implementations like DelegateCommand, etc.

also subscription to event is a safe operation. try-catch around subscription isn't going to catch exceptions from attached event handler. try-catch should be inside handler

ASh
  • 34,632
  • 9
  • 60
  • 82