Как передать переменные в метод события кнопки? - PullRequest
16 голосов
/ 27 января 2011

Мне нужно иметь возможность передавать два объекта вызываемому методу, когда я нажимаю кнопку. Как мне это сделать?

Пока я смотрел на создание измененного 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;
    }
}

Но как бы я это использовал? Можно ли как-то переопределить событие нажатия кнопки, чтобы использовать собственный обработчик событий, который принимает CompArgs в качестве параметра?

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++;
                }
            }
         }

И метод события, где он мне нужен:

private void btn_Click(object sender, CompArgs ca)
        {
                MessageBox.Show((string)ca.Typen().InvokeMember("getMyName",
                             BindingFlags.Default | BindingFlags.InvokeMethod,
                             null,
                             ca.Metode(),
                             null));

        }

Ответы [ 8 ]

49 голосов
/ 30 апреля 2016

Ух ты, ребята, вы делаете это совсем сложно. Нет необходимости в каких-либо пользовательских классах или переопределениях методов. В этом примере мне просто нужно передать индексный номер вкладки. Вы можете указать все, что хотите, если ваш метод ожидает этот тип значения.

button.Click += (sender, EventArgs) => { buttonNext_Click(sender, EventArgs, item.NextTabIndex); };

void buttonNext_Click(object sender, EventArgs e, int index)
    {
       //your code
    }
5 голосов
/ 27 января 2011

Не можете ли вы просто установить свойство или переменную-член в форме, в которой находится кнопка, и получить к ним доступ из события нажатия кнопки?

РЕДАКТИРОВАТЬ: предложение класса пользовательской кнопки после комментария обратной связи (не то же, что и выше)

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
}
3 голосов
/ 27 января 2011

Я бы создал новую кнопку и переопределил метод OnClick.Вместо передачи EventArgs передайте новый производный класс с дополнительными членами.

В делегате, получающем событие, приведите данный EventArgs к более производному классу, который вы ожидаете получить, или установите aновое событие, которое будет вызвано одновременно с нажатием кнопки и подключением к нему, чтобы сделать вещи неявными.

Пример кода:

 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);
}
2 голосов
/ 26 июня 2017

Вы можете использовать Tag свойство кнопки. Вы можете добавить строковое значение к этому свойству из окна свойств конструктора и затем выбрать его в обработчике следующим образом:

    private void MyButton_Click(object sender, EventArgs e)
    {
        string tagValue = ((Button) sender).Tag;

        if(tag == "blah")
        {
            // Do something
        }
    }
2 голосов
/ 27 января 2011

Не уверен, существует ли это в Winforms, но существует в WPF: на всех элементах управления есть объект «tag», к которому вы можете прикрепить любой объект. Вы можете сохранить объект, который хотите передать, и затем в обработчике событий прочитать его обратно из объекта отправителя.

private void Button_Click(object sender, RoutedEventArgs e)
{
    var note = (sender as FrameworkElement).Tag as Note;
    //Do something with note here
}
1 голос
/ 27 января 2011

Вы не можете использовать свой собственный класс аргумента события для предопределенной сигнатуры обработчика событий. По крайней мере, пользовательский тип аргумента события никогда не будет использоваться никакими вызовами по умолчанию к обработчику (который всегда будет иметь тип EventArgs в случае кнопки); потенциально вы могли бы вызвать обработчик самостоятельно, передав свой пользовательский тип, однако вам понадобится логика, чтобы привести его обратно из EventArgs в то, из которого он был приведен.

В качестве возможного решения (в зависимости от вашей ситуации) рассмотрите составной тип для инкапсуляции необходимых вам элементов, как с вашим типом аргумента события, но сохраните требуемый экземпляр как доступную переменную, которую можно использовать из обработчика события или, по крайней мере, с помощью метода (ов), который вызывает четный обработчик.

Например, укажите ваш тип ...

public class MyType
{
    public object AccessibleItem { get; set; }
}

А в твоем классе класс ...

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:

Хорошо, глядя на ваш текущий код, я могу только предложить вам это сейчас (он не добавляет элементы в контейнер управления формами и использует переменный итератор в Linq (который, я думаю, либо осуждается, либо просто не работает) - правильно (?), но эй ...):

    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++
            });
    }
0 голосов
/ 27 января 2011

Если вы откроете файл yourForm.Designer.cs, вы увидите весь код, автоматически сгенерированный VS.Здесь вы можете изменить метод, вызываемый при нажатии на кнопку (или добавить второй метод).

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);

Надеюсь, это поможет.

0 голосов
/ 27 января 2011

Потребуется больше кода, чтобы дать лучший ответ, но вы могли бы создать событие, которое принимает ваши CompArgs в качестве параметра и запускается при захвате buttonEvent

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...