I have an array of buttons which shall all call the same method but with the index of the button as an argument.
using System;
using Gtk;
public class Input : Gtk.Window {
private Gtk.Button[] plus;
public Input() : base(Gtk.WindowType.Toplevel) {
plus = new Button[10];
[…]
for (uint i = 0; i < 10; i++) {
plus[i] = new Button();
plus[i].Name = i.ToString();
plus[i].ButtonPressEvent += AddButtonPressed;
}
}
I tried it using this method, but it seems it gets not even called as there is no output:
protected virtual void AddButtonPressed(object sender, System.EventArgs e) {
Console.WriteLine("Button pressed");
for (uint i = 0; i < plus.Length; i++) {
if (sender.Equals(plus[i])) {
uint index = i;
i = (uint)plus.Length;
Console.WriteLine(index);
}
}
Maybe someone can point me in the right direction?
Thanks.
Quick answer:
Rambling explanation:
This is actually an interesting question. It took a bit of searching to find, but GTK#’s FAQ (but I guess not frequently linked to) says,
If it weren’t for, “public outcry” (rarely a sign of a good interface), there would be no way to avoid this, except subclassing which is sometimes annoying in C# due to the lack of anonymous classes. But luckily, you’re not the first person to have this issue. So that’s where the GLib.ConnectBefore attribute comes in. It basically says, call this event handler first so the event isn’t devoured by Gtk+.
The annoyance doesn’t end there though. I originally was going to suggest applying a good proven solution to passing “extra” parameters to event handlers. In this case, this would allow you to find the index without using equals or the
Namestring It basically involves creating a wrapper delegate that “pretends” to be a ButtonPressEventHandler but internally passes an int to your backing method:It compiles and runs without errors, but it has the same problem, the event never fires. I realized that you can’t put an attribute directly on a delegate/lambda. So even though the backing method has
[GLib.ConnectBefore]the delegate doesn’t, so it fails.As a final note, you could use the Clicked event as in this API example. I verified that it works as expected. One would think that it would only fire on mouse-clicks, but it actually does fire on spacebar as well.