Reputation: 31
I have a custom control in WPF (MenuButton) and want to add a click event handler to a list of them. The event handler requires an integer to be passed into it, like so:
List<MenuButton> mbButtons;
private void SetUpButtons()
{
Random r = new Random();
foreach (MenuButton item in mbButtons)
{
SubscribeToClickEvent(item, r.Next(0, 11));
}
}
private void SubscribeToClickEvent(MenuButton mb, int i)
{
mb.Click += (sender, e) => MyClickEvent(sender, e, i);
}
But how do I then unsubscribe from the event for each button?
Upvotes: 0
Views: 115
Reputation: 35679
it makes more sense to keep relevant data in button instance, and retrive it in event handler:
List<MenuButton> mbButtons;
private void SetUpButtons()
{
Random r = new Random();
foreach (MenuButton item in mbButtons)
{
item.Tag = r.Next(0, 11);
item.Click += MyClickEvent;
}
}
private void MyClickEvent(object sender, RoutedEventArgs e)
{
var mb = (MenuButton)sender;
int i = (int)mb.Tag;
}
then unsubscribe without any difficulties using known method name:
mb.Click -= MyClickEvent;
Upvotes: 1
Reputation: 42245
You need to store the delegate, and use it again to unsubscribe.
private RoutedEventHandler handler;
private void SubscribeToClickEvent(MenuButton mb, int i)
{
handler = (sender, e) => MyClickEvent(sender, e, i);
mb.Click += handler;
}
private void UnsubscribeFromClickEvent(MenuButton mb)
{
mb.Click -= handler;
handler = null;
}
Of course, add your own logic to handle the case where SubscribeToClickEvent
is called more than once.
You edited your question to have an array of buttons, so here's an adjusted answer:
You will need to keep a list of delegate instances to remove:
private List<MenuButton> mbButtons;
private readonly List<(MenuButton button, RoutedEventHandler handler)> clickHandlers = new List<(MenuButton, RoutedEventHandler)>();
private void SetUpButtons()
{
Random r = new Random();
foreach (MenuButton item in mbButtons)
{
SubscribeToClickEvent(item, r.Next(0, 11));
}
}
private void SubscribeToClickEvent(MenuButton mb, int i)
{
RoutedEventHandler handler = (sender, e) => MyClickEvent(sender, e, i);
clickHandlers.Add((mb, handler));
mb.Click += handler;
}
private void UnsubscribeFromClickEvents()
{
foreach (var (button, handler) in clickHandlers)
{
button.Click -= handler;
}
clickHandlers.Clear();
}
Upvotes: 2
Reputation: 564
It's been a while since I worked with WPF but I'm pretty sure you can just have another method that does the opposite:
private void UnsubscribeToClickEvent(MenuButton mb, int i)
{
mb.Click -= (sender, e) => MyClickEvent(sender, e, i);
}
Upvotes: -1