2009-09-28 5 views
11

Visual Studio 2008, C# 3.0.Aufruf eines Eventhandlers mit Argumenten

Ich habe eine Methode, die einen Event-Handler ruft. Ich möchte die zwei Argumente, die von der Methode empfangen werden, an den Ereignishandler übergeben.

Ich möchte so etwas wie dies tun:

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

Ist dies überhaupt möglich, wenn ja, wie würde ich mich dagegen zu tun?

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

Antwort

25

Der einfachste Weg, dies zu tun, ist eine anonyme Funktion (eine anonyme Methode oder einen Lambda-Ausdruck) zu verwenden, um das Ereignis zu abonnieren, dann Ihre Methode hat macht nur die Parameter, die Sie wollen:

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

Super !! Wer hätte das gedacht !! – dezkev

+3

Wie können Sie die Veranstaltung abbestellen? – jdelator

+2

@jdelator: Sie müssten den Delegaten in einer Variablen speichern und diese zum Abbestellen verwenden. –

4

DownloadDataAsync eine Überlastung hat, die eine Aufgabe übernimmt:

DownloadDataAsync(uri, object) 

Das Objekt kann jede beliebige, was Sie wollen, dass in die DownloadDataCompleted handler geben wird:

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

Jon's Version ist funky, aber das funktioniert und ist kompatibel mit Nicht-3.5-Sachen. – womp

+0

@womp Jon's Version ist funky genial, aber das funktioniert und ist kompatibel mit nicht-3,5 Sachen :) –

+0

So sind wir uns einig. Es ist funky genial. – womp

2

Sie könnten eine private Klasse schaffen und dort den Handler platzieren. Z.B.

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

Obwohl, angesichts der Eleganz von Jons Antwort würde wahrscheinlich das verwenden!

1

Jon Skeet hat dies bereits beantwortet und gezeigt, wie man einen Lamda-Ausdruck verwendet, aber ich war noch nicht klar darüber. Ich brauchte noch einige weitere Beispiele, und schließlich fand diese einfachen Fall mit Hilfe einer Schaltfläche: 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); 
} 


In meinem Fall war ich für ein TreeView-Steuerelement ein Kontextmenü, das wie am Ende der Suche dies:

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" 
}