2010-10-01 57 views
8

我有一個USerControll,我有一個文本框。我在表單中使用usercontrol,當某人按下文本框中的輸入時,我想要執行某些操作。我該怎麼做? 如果你告訴我如何手動調用一個事件,我可以在textbox.keydown中調用usercontrol.keydown。如何在C#中手動調用事件?

+0

所以你想從TextBox.KeyDown事件處理程序中引發UserControl.KeyDown事件,對嗎? – dtb 2010-10-01 16:36:42

+0

因此,當用戶實際按下keydown時對事件做出響應對於您的場景是不夠的?我想我在你的場景中錯過了一些東西。 – RQDQ 2010-10-01 16:36:53

+0

@dtb:是的,恰到好處 – Saeed 2010-10-01 16:46:54

回答

10

首先,事件只能由聲明事件的控件中的代碼引發。因此,您的用戶控件必須聲明自定義事件KeyDown以提升它。舉例來說,你不能在你的用戶控件所包含的TextBox中引發KeyDown。但是,您可以聲明自己的KeyDown,並將一個處理程序附加到TextBox的KeyDown中,這會引發您自己的KeyDown。

鑑於此限制,引發一個事件很容易:

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

引發事件看起來很像一個方法,因爲在本質上這是你在做什麼;您正在調用一個或多個方法委託,這些方法委派在事件的場景後分配給MultiCast委託。把它看作是將一個方法分配給一個普通的命名委託(就像你從定義中省略了「event」關鍵字)並從代碼中調用它。真正的事件和唯一的區別是一個事件可以有多個處理程序委託,並且在引發時會調用它們。

+0

不幸的是,這段代碼不是線程安全的。您需要創建一個'MyEvent'的本地副本,以防止在另一個線程同時刪除'if'和事件調用之間的所有事件處理程序時引發'NullReferenceExceptions'。 – 2010-10-01 16:49:19

+0

...或在評估if之前鎖定(MyEvent()),然後釋放它。這個問題僅僅是關於提出一個事件,這就是我回答的問題;如果他無情地依附和分離處理程序,這表明對事件的更先進的瞭解,不需要提出問題。 – KeithS 2010-10-01 16:53:38

+0

你原則上是對的,但這不是我的意思:在當地複製事件是一個牢固確立的最佳實踐。 *沒有*事件提升代碼應該永遠不會被編寫,甚至沒有作爲一個例子(因爲如果你不指望多線程問題,你不會想到它)。附加事件不是用戶控件的代碼可以控制的 - 這取決於用戶。作爲可重用的代碼,用戶控制代碼應該儘可能健壯。 – 2010-10-01 17:02:49

0

您描述的內容稱爲事件冒泡。下面是一個例子:

<%@ 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

只是爲了澄清,因爲我可能誤解了這個問題。你正在尋找'輸入'具體還是你想通過文本框捕獲提交? – 2010-10-01 16:47:53

1

典型地,事件invokation被包裹在一個名字類似方法 「[事件名稱]」 這驗證該delgate有一個或多個目標(事件不爲空),然後與發件人和任何目標調用它適用參數...所以像這樣的典型模式:需要提高的是事件

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

任何調用該方法(假設它的訪問)。

如果您只是想傳遞事件,那麼作爲UserControl,您可能只需調用可能暴露的基礎「On [Event]」方法。您也可以連接事件處理程序,以直接從子控件傳遞事件作爲父控件的事件,以便txtFoo.KeyPress只是調用父控件的OnKeyPress方法。

0

如果您正在使用WPF,你也許能夠使用的RaiseEvent:http://msdn.microsoft.com/en-us/library/system.windows.uielement.raiseevent.aspx

但是,這是不對的,你想要做什麼。

你應該冒泡事件。

class MyControl : UserControl { 
    public KeyDownEventHandler KeyDown; 

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

然後從您的表單中收聽KeyDown。請原諒各種元素/事件的錯誤。

2

我一直在尋找的答案,這個問題對我來說,

只是這樣做

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 
     } 

我希望這是對你有用。