Reputation: 1340
I need to be able to pass along two objects to the method being fired when I click a button. How do I do this?
So far I've been looking at creating a changed EventArgs
:
public class CompArgs : System.EventArgs
{
private object metode;
private Type typen;
public CompArgs(object m, Type t)
{
this.metode = m;
this.typen = t;
}
public object Metode()
{
return metode;
}
public Type Typen()
{
return typen;
}
}
But how would I use it? Is it possible to somehow override the click-event of the button to use a custom eventhandler
, which takes CompArgs
as a parameter?
private void button1_Click(object sender, EventArgs e)
{
Assembly assembly = Assembly.LoadFile(@"c:\components.dll");
int counter = 0;
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass == true)
{
Button btn = new Button();
btn.Location = new Point(174 + (counter * 100),10);
btn.Size = new Size(95, 23);
btn.Name = type.Name;
btn.Text = type.Name;
btn.UseVisualStyleBackColor = true;
this.Controls.Add(btn);
object obj = Activator.CreateInstance(type);
//I need to pass on obj and type to the btn_Click
btn.Click += new eventHandler(btn_Click);
counter++;
}
}
}
And the event-method where I need it:
private void btn_Click(object sender, CompArgs ca)
{
MessageBox.Show((string)ca.Typen().InvokeMember("getMyName",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
ca.Metode(),
null));
}
Upvotes: 26
Views: 94059
Reputation: 2935
You could use the Tag property of the button. You can add a string value to this property from the designer properties window and then pick it up within the handler as so:
private void MyButton_Click(object sender, EventArgs e)
{
string tagValue = ((Button) sender).Tag;
if(tag == "blah")
{
// Do something
}
}
Upvotes: 4
Reputation: 1468
Wow, you guys are making this entirely to difficult. No need for any custom classes or method overrides. In this example I just need to pass a tab index number. You can specify whatever you want, so long as your method is expecting that value type.
button.Click += (sender, EventArgs) => { buttonNext_Click(sender, EventArgs, item.NextTabIndex); };
void buttonNext_Click(object sender, EventArgs e, int index)
{
//your code
}
Upvotes: 79
Reputation: 45083
You can't use your own custom event argument class for a predefined event handler signature. At least, the custom event argument type will never be utilised by any default calls to the handler (which will only ever be of type EventArgs
in the case of a button); you could, potentially, call the handler yourself, passing your custom type, however, you would need to have logic in order to cast it back from an EventArgs
into that which it had been cast from.
As a possible solution (depending on your situation), consider a composite type to encapsulate the items you require, as with your event argument type, but keep the required instance as an accessible variable which can be utilised from within the event handler, or, at least, by the method/s which the even handler invokes.
For example, define your type...
public class MyType
{
public object AccessibleItem { get; set; }
}
And, in your form class...
private MyType MyTypeInstance = new MyType();
private void Button_Click(object sender, EventArgs e)
{
//here we can set the item, if needs be...
MyTypeInstance.AccessibleItem = new Anything();
//or access the item to use as required...
DoSomeMagicWithMyObject(MyTypeInstance.AccessibleItem);
}
EDIT:
Okay, looking at your current code I can only offer you this for now (it doesn't add the items to the forms control container and it uses a variable iterator within Linq (which I think is either frowned upon or just down-right wrong (?), but hey...):
private void BuildButtonToObjectDictionary()
{
int counter = 0;
var assembly = Assembly.LoadFile(@"c:\components.dll");
var buttonToObjectDictionary = (
from type in assembly.GetTypes()
where type.IsClass && !type.IsAbstract
select new
{
Button = new Button
{
Name = type.Name,
Text = type.Name,
Size = new Size(95, 25),
Location = new Point(175 + (counter * 100), 10),
UseVisualStyleBackColor = true
},
Item = Activator.CreateInstance(type),
Index = counter++
});
}
Upvotes: 2
Reputation: 34489
I'd create a new Button and override the OnClick method. Rather than passing down the EventArgs, pass a new derived class in with your additional members.
On the delegate receiving the event, cast the given EventArgs to the more derived class you're expecting to get, alternatively setup a new Event that will be triggered at the same time when the button is pressed and hook up to that instead to make things more implicit.
Example Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ButtonEx b1 = new ButtonEx();
b1.OnCustomClickEvent += new ButtonEx.OnCustomClickEventHandler(b1_OnCustomClickEvent);
}
void b1_OnCustomClickEvent(object sender, ButtonEx.CustomEventArgs eventArgs)
{
string p1 = eventArgs.CustomProperty1;
string p2 = eventArgs.CustomProperty2;
}
}
public class ButtonEx : Button
{
public class CustomEventArgs : EventArgs
{
public String CustomProperty1;
public String CustomProperty2;
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
if(OnCustomClickEvent != null)
{
OnCustomClickEvent(this, new CustomEventArgs());
}
}
public event OnCustomClickEventHandler OnCustomClickEvent;
public delegate void OnCustomClickEventHandler(object sender , CustomEventArgs eventArgs);
}
Upvotes: 3
Reputation: 18013
Cant you just set a property or member variable on the form that hosts the button and access these from the button click event?
EDIT: custom button class suggestion after feedback comment (not the same suggestion as above)
class MyButton : Button
{
private Type m_TYpe;
private object m_Object;
public object Object
{
get { return m_Object; }
set { m_Object = value; }
}
public Type TYpe
{
get { return m_TYpe; }
set { m_TYpe = value; }
}
}
Button1Click(object sender, EventArgs args)
{
MyButton mb = (sender as MyButton);
//then you can access Mb.Type
//and Mb.object
}
Upvotes: 8
Reputation: 8058
Not sure if this exists in Winforms but it does in WPF: There is a "tag" object on all controls which you can attach any object to. You could save the object that you want to pass and then in the event handler read it back out of the sender object.
private void Button_Click(object sender, RoutedEventArgs e)
{
var note = (sender as FrameworkElement).Tag as Note;
//Do something with note here
}
Upvotes: 2
Reputation: 25435
If you open yourForm.Designer.cs file you will see all the code auto generated by VS. Here you can alter the method called when clicking on the button (or add a second method).
this.yourButton.Location = new System.Drawing.Point(211, 51);
this.yourButton.Name = "yourButton";
this.yourButton.Size = new System.Drawing.Size(75, 23);
this.yourButton.TabIndex = 0;
this.yourButton.Text = "yourButton";
this.yourButton.UseVisualStyleBackColor = true;
this.yourButton.Click += new System.EventHandler(this.yourMethodHere(object1, object2);
Hope this helps.
Upvotes: 0
Reputation: 27357
Would need to see more code to give a better answer, but you could create an event that takes your CompArgs as a parameter and is fired when the buttonEvent is captured
Upvotes: 0