réponse rapide:
[GLib.ConnectBefore]
protected virtual void AddButtonPressed(object sender, 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);
}
}
}
explication Rambling:
Ceci est en fait une question intéressante. Il a fallu un peu de recherche à trouver, mais GTK#'s FAQ (mais je suppose que pas souvent liée à) dit,
« Avec la version 0.15, Gtk # a commencé en utilisant le drapeau connect_after lors reliant les gestionnaires d'événements aux signaux. cela signifie que les gestionnaires d'événements sont ne courir qu'après le signal par défaut gestionnaires, ce qui signifie que le widget sera mis à jour lorsque l'événement exécution des gestionnaires. Un effet secondaire de ce changement est que dans le cas où défaut les gestionnaires retournent à pour signaler la propagation du signal, Gtk # eve nts ne sera pas émis. C'est le cas pour l'exemple dans Gtk.Button, où le gestionnaire de signal par défaut de bouton-presse-événement-événement est ignoré pour émettre des événements pressés.
Bien que potentiellement confus, c'est pas vraiment un bug. Lorsque vous utilisez un Gtk.Button, vous obtenez un widget qui émet des événements pressés en réponse à des pressions Button1. Si vous voulez également votre bouton pour changer les couleurs, ou un menu contextuel sur les presses Button3, ce n'est pas un Gtk.Button. La bonne façon de mettre en œuvre un tel widget est sous-classe Gtk.Button et remplacer la méthode virtuelle OnButtonPressEvent à mettre en œuvre les nouveaux comportements que vous souhaitez ."
S'il n'y avait pas, « tollé général »(rarement un signe d'une bonne interface), il n'y aurait aucun moyen d'éviter cela, sauf subclassing qui est parfois gênant en C# en raison du manque de Heureusement, vous n'êtes pas la première personne à avoir ce problème.C'est donc là que l'attribut GLib.ConnectBefore entre en jeu. Il dit en gros, appelez ce gestionnaire d'événements d'abord pour que l'événement ne soit pas dévoré par Gtk +
L'ennui ne s'arrête pas là: à l'origine, je proposais d'appliquer une bonne solution éprouvée pour passer des paramètres "supplémentaires" aux gestionnaires d'événements, ce qui vous permettrait de trouver l'index sans Name
chaîne Il essentiellement je mpl quent la création d'un délégué wrapper qui « fait semblant » d'être un ButtonPressEventHandler mais passe en interne un entier à votre méthode de support:
Func<uint, ButtonPressEventHandler> indexWrapper = ((index) => ((s, e) => { AddButtonPressed_wrapped(s, e, index); }));
...
plus[i].ButtonPressEvent += indexWrapper(i);
...
protected virtual void AddButtonPressed_wrapped(object sender, EventArgs e, uint index)
{
Console.WriteLine("Button pressed");
Console.WriteLine("Index = {0}", index);
}
Il compile, et fonctionne sans erreur, mais il a le même problème, l'événement ne se déclenche. J'ai réalisé que vous ne pouvez pas mettre un attribut directement sur un délégué/lambda. Donc, même si la méthode de sauvegarde a [GLib.ConnectBefore]
le délégué ne fonctionne pas, donc il échoue. Pour finir, vous pouvez utiliser l'événement Clicked comme dans this API example. J'ai vérifié que cela fonctionne comme prévu. On pourrait penser qu'il ne se déclencherait que sur des clics de souris, mais il se déclencherait aussi sur la barre d'espace.
J'ai pris le chemin court hacky pour l'instant ;-) Merci pour cette réponse très détaillée et votre temps investi! Une petite correction d'ailleurs: ça doit être [GLib.ConnectBeforeAttribute] –
En fait, ça marche dans les deux sens. Voir http://www.go-mono.com/docs/index.aspx?link=C%3AGtk.ButtonPressEventArgs. Je viens aussi de trouver http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx, qui dit "Par convention, tous les noms d'attribut se terminent par le mot" Attribute "pour les distinguer des autres Dans le .NET Framework, vous n'avez pas besoin de spécifier le suffixe d'attribut lorsque vous utilisez des attributs dans le code. " –