2009-09-28 6 views
11

Visual Studio 2008, C# 3.0.appelle un eventhandler avec des arguments

J'ai une méthode ci-dessous qui appelle un gestionnaire d'événements. Je voudrais passer les deux arguments reçus par la méthode au gestionnaire d'événements.

Je voudrais faire quelque chose comme ceci:

wc.DownloadDataCompleted += wc.DownloadedDataCompleted(strtitle, placeid); 

Est-ce même possible, si oui, comment pourrais-je aller à le faire?

Code Snippet:

public void downloadphoto(string struri,string strtitle,string placeid) 
{ 
    using (WebClient wc = new WebClient()) 
    { 
     wc.DownloadDataCompleted += wc_DownloadDataCompleted; 
     wc.DownloadDataAsync(new Uri(struri)); 
    } 
} 

Répondre

25

La meilleure façon de le faire est d'utiliser une fonction anonyme (une méthode anonyme ou une expression lambda) pour souscrire à l'événement, alors que votre méthode avez juste le paramètres que vous voulez:

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's used :) 
private void DownloadDataCompleted(string title, string id, 
            DownloadDataCompletedEventArgs args) 
{ 
    // Do stuff here 
} 
+1

Impressionnant !! maintenant qui aurait thunk ça !! – dezkev

+3

Comment vous désinscrire de l'événement? – jdelator

+2

@jdelator: Vous devez stocker le délégué dans une variable et l'utiliser pour vous désabonner. –

4

DownloadDataAsync a une surcharge qui prend un objet:

DownloadDataAsync(uri, object) 

Cet objet peut être quelque chose arbitraire que vous voulez qui est passé dans le 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]; 
} 
+0

La version de Jon est funky, mais cela fonctionne et est compatible avec des choses non-3.5. – womp

+0

@womp La version de Jon est génial génial, mais cela fonctionne et est compatible avec des trucs non-3,5 :) –

+0

Donc, nous sommes d'accord. C'est génial génial. – womp

2

Vous pouvez créer une classe privée et placez le gestionnaire là-dedans. Par exemple. Bien que, compte tenu de l'élégance de la réponse de Jon serait probablement utiliser cela!

1

Jon Skeet a déjà répondu à cette question, en montrant comment utiliser une expression lamda, mais je n'étais toujours pas clair à ce sujet. Je encore besoin d'autres exemples, et finalement trouvé ce cas simple en utilisant un bouton: 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); 
} 


Dans mon cas, j'utilisais un menu contextuel pour un contrôle TreeView, qui a fini par ressembler à ceci:

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's 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" 
} 
Questions connexes