Вызвать обработчик событий с аргументами
Visual Studio 2008, С# 3.0.
У меня есть метод, который вызывает обработчик события. Я хотел бы передать два аргумента, полученные методом обработчику событий.
Я хотел бы сделать что-то вроде этого:
wc.DownloadDataCompleted += wc.DownloadedDataCompleted(strtitle, placeid);
Возможно ли это, если да, как мне это сделать?
Фрагмент кода:
public void downloadphoto(string struri,string strtitle,string placeid)
{
using (WebClient wc = new WebClient())
{
wc.DownloadDataCompleted += wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri));
}
}
Ответы
Ответ 1
Самый простой способ сделать это - использовать анонимную функцию (анонимный метод или выражение лямбда) для подписки на событие, а затем сделать свой метод только теми параметрами, которые вы хотите:
public void downloadphoto(string struri, string strtitle, string placeid)
{
using (WebClient wc = new WebClient())
{
wc.DownloadDataCompleted += (sender, args) =>
DownloadDataCompleted(strtitle, placeid, args);
wc.DownloadDataAsync(new Uri(struri));
}
}
// Please rename the method to say what it does rather than where it used :)
private void DownloadDataCompleted(string title, string id,
DownloadDataCompletedEventArgs args)
{
// Do stuff here
}
Ответ 2
DownloadDataAsync
имеет перегрузку, которая принимает объект:
DownloadDataAsync(uri, object)
Этот объект может быть любой произвольной вещью, которую вы хотите передать в DownloadDataCompleted handler
:
public void downloadphoto(string struri,string strtitle,string placeid)
{
using (WebClient wc = new WebClient())
{
string[] data = new string[2] { strtitle, placeid };
wc.DownloadDataCompleted += wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri), data);
}
}
void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string[] data = (string[])e.UserToken;
string strtitle = data[0];
string placeid = data[1];
}
Ответ 3
Вы можете создать частный класс и разместить там обработчик. Например.
public void downloadphoto(string struri, string strtitle, string placeid)
{
using (WebClient wc = new WebClient())
{
wcHandler handler = new wcHandler() { Strtitle = strtitle, Placeid = placeid };
wc.DownloadDataCompleted += handler.wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri));
}
}
private class wcHandler
{
public string Strtitle { get; set; }
public string Placeid { get; set; }
public void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
// Do Stuff
}
}
Хотя, учитывая элегантность ответа Джона, вероятно, будет использовать это!
Ответ 4
Jon Skeet уже ответил на это, показывая, как использовать выражение lamda, но я все еще не совсем понял. Мне все еще нужно было еще несколько примеров, и в итоге я нашел этот простой случай с помощью кнопки: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/74d03fe0-0fa5-438d-80e0-cf54fa15af0e
void A()
{
Popup parameter = new Popup();
buttonClose.Click += (sender, e) => { buttonClose_Click(sender, e, parameter); };
}
static void buttonClose_Click(object sender, EventArgs e, Popup parameter)
{
MakeSomethingWithPopupParameter(parameter);
}
В моем случае я использовал контекстное меню для элемента управления TreeView, который выглядел следующим образом:
private void TreeViewCreateContextMenu(TreeNode node)
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
// create the menu items
ToolStripMenuItem newMenuItem = new ToolStripMenuItem();
newMenuItem.Text = "New...";
// add the menu items to the menu
contextMenu.Items.AddRange(new ToolStripMenuItem[] { newMenuItem });
// add its event handler using a lambda expression, passing
// the additional parameter "myData"
string myData = "This is the extra parameter.";
newMenuItem.Click += (sender, e) => { newMenuItem_Click(sender, e, myData); };
// finally, set the node context menu
node.ContextMenuStrip = contextMenu;
}
// the custom event handler, with "extraData":
private void newMenuItem_Click(object sender, EventArgs e, string extraData)
{
// do something with "extraData"
}