2010-10-01 29 views
8

Ho un controllo USER in cui ho una casella di testo. Uso l'usercontrol nella mia forma, voglio fare qualcosa quando qualcuno preme entrare nella casella di testo. Come posso farlo? se mi dici come chiamare manualmente un evento, posso chiamare usercontrol.keydown in textbox.keydown.Come chiamare un evento manualmente in C#?

+0

Quindi si desidera aumentare l'evento UserControl.KeyDown dal gestore di eventi TextBox.KeyDown, è corretto? – dtb

+0

Quindi rispondere all'evento quando l'utente preme effettivamente un keydown non è abbastanza per il tuo scenario? Penso che mi manchi qualcosa nel tuo scenario. – RQDQ

+0

@dtb: sì, giusto – Saeed

risposta

10

Innanzitutto, gli eventi possono essere generati solo dal codice all'interno del controllo che dichiara l'evento. Pertanto, il controllo utente deve dichiarare l'evento personalizzato KeyDown per poterlo generare. Ad esempio, non puoi aumentare KeyDown su un TextBox contenuto dal tuo controllo utente. Tuttavia, puoi dichiarare il tuo KeyDown e associare un gestore al KeyDown del TextBox che genererà il tuo KeyDown.

Data questa limitazione, sollevando un evento è facile:

public delegate void MyEventHandler(object sender, MyEventArgs e) 

public event MyEventHandler MyEvent; 

public void RaisesMyEvent() 
{ 
    ... 

    if(MyEvent != null) //required in C# to ensure a handler is attached 
     MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/)); 
} 

generazione di un evento si presenta molto simile a un metodo, perché in sostanza questo è quello che stai facendo; stai chiamando uno o più delegati metodo assegnati al delegato MultiCast dietro le quinte del tuo evento. Consideralo come se assegnassi un metodo a un ordinario delegato chiamato (come se tu avessi omesso la parola chiave "evento" dalla definizione) e chiamandolo dal tuo codice. l'unica differenza tra un vero evento e cioè che un evento può avere più di un delegato gestore ad esso allegato, e invocherà tutti quando generato.

+0

Sfortunatamente, questo codice non è thread-safe. È necessario creare una copia locale di 'MyEvent' per salvare-guard contro' NullReferenceExceptions' che si presentano quando un altro thread rimuove contemporaneamente tutti i gestori di eventi tra il tuo if e il richiamo dell'evento. –

+0

... Oppure bloccare (MyEvent()) prima di valutare l'if e rilasciarlo in seguito. La domanda era semplicemente di innalzare un evento ed è quello che ho risposto; se sta attaccando e staccando i gestori, volente o nolente, ciò indica una conoscenza più avanzata degli eventi in generale, che preclude la necessità di porre la domanda. – KeithS

+0

Hai ragione, in linea di principio, ma non è quello che intendo: copiare l'evento localmente è una best practice ben consolidata. * Nessun codice di innalzamento degli eventi dovrebbe mai essere scritto senza di esso, nemmeno come esempio (poiché se non ti aspetti il ​​problema del multithreading, non ci penserai). Allegare eventi nilly-willy non è qualcosa che il codice del controllo utente può controllare: dipende dall'utente. Come codice riutilizzabile, il codice di controllo dell'utente dovrebbe essere il più robusto possibile. –

0

Quello che descrivi è chiamato evento spumeggiante. Ecco un esempio:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyUserControl.ascx.cs" Inherits="MyUserControl" %> 

<asp:TextBox ID="TextBox1" runat="server" OnTextChanged="TextBox1_TextChanged" /> 

public partial class MyUserControl : UserControl 
{ 
public event EventHandler UserControlTextBoxChanged; 

protected void TextBox1_TextChanged(object sender, EventArgs e) { 
    if (UserControlTextBoxChanged != null) 
    UserControlTextBoxChanged(sender, e); 
} 
} 

<%@ Page Language="C#" AutoEventWireup="True" Inherits="Default" CodeBehind="Default.aspx.cs" %> 
<%@ Register Src="~/MyUserControl.ascx" TagName="MyUserControl" TagPrefix="uc1" %> 

<uc1:MyUserControl ID="ucMyUserControl" runat="server" OnUserControlTextBoxChanged="ucMyUserControl_UserControlTextBoxChanged" /> 

public partial class MyPage : Page { 
protected void ucMyUserControl_UserControlTextBoxChanged(object sender, EventArgs e) { 
    // sender is ucMyUserControl.TextBox1 
} 
} 
+0

Giusto per chiarire come potrei aver frainteso la domanda. Stai cercando "Invio" in modo specifico o stai tentando di acquisire un invio tramite TextBox? –

1

In genere, l'invocazione evento è avvolto in un metodo denominato qualcosa come "On [EventName]" che convalida che il Delgate ha uno o più bersagli (l'evento non è nullo) e quindi lo richiama con il mittente e qualsiasi argomenti applicabili ... quindi qualcosa di simile è il modello tipico:

public event EventHandler SomethingHappened; 
protected void OnSomethingHappend(EventArgs e) 
{ 
    if (SomethingHappened != null) 
     SomethingHappened(this, e); 
} 

Tutto ciò che deve sollevare quell'evento invoca tale metodo (supponendo sua accessibile).

Se si desidera semplicemente passare l'evento, quindi come un controllo utente, è possibile semplicemente invocare il metodo base "On [evento]", che è probabilmente esposto. Puoi anche collegare i gestori di eventi per passare direttamente l'evento da un controllo figlio come evento del controllo genitore ... in modo che txtFoo.KeyPress invochi semplicemente il metodo OnKeyPress del controllo genitore.

0

Se si utilizza WPF, si potrebbe essere in grado di utilizzare RaiseEvent: http://msdn.microsoft.com/en-us/library/system.windows.uielement.raiseevent.aspx

Ma questo è sbagliato per quello che si vuole fare.

Si dovrebbe bolla l'evento.

class MyControl : UserControl { 
    public KeyDownEventHandler KeyDown; 

    private void OnTextBoxKeyDown(object sender, EventArgs e){ KeyDown.Invoke(sender, e); } 
} 

Quindi ascoltare KeyDown dal modulo. Si prega di scusare gli errori nella denominazione dei vari elementi/eventi.

2

ero alla ricerca di una risposta a questo problema per me,

solo fare questo

examble:

//this is the call to trigger the event: 

**lst_ListaDirectorios_SelectedIndexChanged(this, new EventArgs());** 

//do that if you have the method signature in the same class as I do. (something like this below) 
private void lst_ListaDirectorios_SelectedIndexChanged(object sender, EventArgs e) 
     { 
      //do something 
     } 

Spero che questo è stato utile per voi.

Problemi correlati