2009-09-28 17 views
11

Visual Studio 2008, C# 3.0.wywołanie zdarzenia z argumentami

Mam metodę poniżej, która wywołuje procedurę obsługi zdarzeń. Chciałbym przekazać dwa argumenty otrzymane przez metodę do obsługi zdarzenia.

chciałbym zrobić coś takiego:

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

Czy to w ogóle możliwe, jeśli tak, to jak bym go o to robi?

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

Odpowiedz

25

Najprostszym sposobem, aby to zrobić jest użycie anonimową funkcję (metody anonimowej lub wyrażenie lambda), aby zapisać się do tego wydarzenia, a następnie dokonać metoda ma tylko parametry chcesz:

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

Niesamowite !! teraz kto by to powiedział! – dezkev

+3

Jak zrezygnować z subskrypcji wydarzenia? – jdelator

+2

@jdelator: Będziesz musiał przechowywać delegata w zmiennej i użyć go do anulowania subskrypcji. –

4

DownloadDataAsync ma przeciążenie który przyjmuje obiekt:

DownloadDataAsync(uri, object) 

że obiekt może mieć dowolną rzeczą, którą chcę, że zostanie przeniesiony do 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

Wersja Jona jest funky, ale działa i jest kompatybilny z non-3.5 rzeczy. – womp

+0

@womp Wersja Jona to funky niesamowite, ale to działa i jest kompatybilne z materiałami innymi niż 3.5 :) –

+0

Zgadzamy się. To jest niesamowite. – womp

2

Można by utworzyć prywatną klasę obsługi i umieścić tam. Na przykład.

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

Chociaż, biorąc pod uwagę elegancję odpowiedzi Jona, prawdopodobnie użyłby tego!

1

Jon Skeet już odpowiedział na to, pokazując, jak używać wyrażenia lamda, ale wciąż nie wiedziałem o tym. Wciąż potrzebne jeszcze kilka przykładów, a ostatecznie uznał ten prosty przykład za pomocą przycisku: 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); 
} 


w moim przypadku, byłem przy użyciu menu kontekstowego dla kontrolki TreeView, który zakończył się patrząc jak to:

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" 
} 
Powiązane problemy