C # передача дополнительных параметров в обработчик событий? - PullRequest
55 голосов
/ 18 ноября 2010

Допустим, я хочу передать некоторые дополнительные данные при назначении обработчика событий.Рассмотрим следующий код:

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}

Как мне получить некоторые данные в моем методе evHandler?

Ответы [ 8 ]

51 голосов
/ 18 ноября 2010
private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}
22 голосов
/ 06 января 2016

Мне было трудно разобраться с приведенным выше примером @ spender, особенно с: Object.assignHandler((sender) => evHandler(sender,someData));, потому что нет такой вещи, как Object.assignHandler в буквальном смысле.Таким образом, я сделал немного больше поиска и нашел этот пример .Ответ Питера Дунихо был тот, который щелкнул в моей голове (это не моя работа):

snip

Обычный подход заключается в использовании анонимного метода с обработчиком событийэто ваша измененная подпись.Например:

void Onbutton_click(object sender, EventArgs e, int i) { ... }

button.Click += delegate(object sender, EventArgs e) 
{ Onbutton_click(sender, e, 172); };

Конечно, вам не нужно передавать 172 или даже делать третий параметр целым.:)

/ snip

Используя этот пример, я смог передать два пользовательских ComboBoxItem объекта в событие Timer.Elapsed, используя лямбда-нотацию:

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);

и затем в его обработчик:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }

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

Этот код работает в моем проекте (за исключением не поточнобезопасного исключения с объектами ComboBoxItem, которое, я не верю, меняет работу примера).Сейчас я это выясняю.

18 голосов
/ 18 ноября 2010

Захваченные переменные:

private void setup(string someData)
{
    Object.assignHandler((sender,args) => {
        evHandler(sender, someData);
    });
}

public void evHandler(Object sender, string someData)
{
    // use someData here
}

Или (альтернатива C # 2.0):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });
3 голосов
/ 18 декабря 2013

вы можете попробовать сделать это:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}
1 голос
/ 03 марта 2017

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

class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }
0 голосов
/ 03 августа 2016

Вот мое однострочное решение, которое передает дополнительные параметры обработчику таймера.

private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}
0 голосов
/ 21 февраля 2015

Вы можете создать пользовательский объект с дополнительными свойствами на основе объекта:

class CustomObject : Object
{
    public string SomeData;
}

private void setup(string someData)
{
    CustomObject customObject = new CustomObject { SomeData = someData };
    CustomObject.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    string someData = ((CustomObject)sender).SomeData;
}

Если данные больше не нужно изменять после инициализации, вы также можете добавить пользовательский конструктор, например.

0 голосов
/ 18 ноября 2010

Ну, самый простой идентификатор метода, чтобы сделать someData переменную-член следующим образом:

public class MyClass
{
    private string _eventData;

    private void setup(string someData) 
    {
       _eventData = someData;
       Object.assignHandler(evHandler);
    }

    public void evHandler()
    {
        // do something with _eventData here
    }
}

Я не уверен, что это лучший способ сделать это, но этодействительно зависит от типа события, объекта и т. д.

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