2010-10-01 4 views
8

У меня есть USerControll, в котором у меня есть текстовое поле. Я использую usercontrol в своей форме, я хочу что-то сделать, когда кто-то нажимает кнопку ввода в текстовое поле. как мне это сделать? Если вы скажете мне, как вызвать событие вручную, я могу вызвать usercontrol.keydown в textbox.keydown.Как вызвать событие вручную в C#?

+0

Итак, вы хотите поднять событие UserControl.KeyDown из обработчика события TextBox.KeyDown, правильно? – dtb

+0

Так что реагировать на событие, когда пользователь на самом деле нажимает keydown, недостаточно для вашего сценария? Я думаю, что в вашем сценарии чего-то не хватает. – RQDQ

+0

@dtb: yes, just right – Saeed

ответ

10

Во-первых, события могут быть подняты только из кода внутри элемента управления, объявляющего событие. Таким образом, ваш пользовательский элемент управления должен объявить пользовательское событие KeyDown, чтобы поднять его. Вы не можете, например, поднять KeyDown на TextBox, содержащиеся в вашем пользовательском элементе управления. Однако вы можете объявить свой собственный KeyDown и присоединить обработчик к KeyDown в TextBox, который поднимет ваш собственный 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 за кулисами вашего события. Подумайте об этом как о назначении метода обычным именованным делегатам (например, если вы опустили ключевое слово «событие» из определения) и вызвали его изнутри вашего кода. единственное различие между истинным событием и тем, что событие может иметь более одного делегата обработчика, прикрепленного к нему, и будет вызывать все из них при поднятии.

+0

К сожалению, этот код не является потокобезопасным. Вам необходимо создать локальную копию 'MyEvent' для сохранения защиты от' NullReferenceExceptions', возникающую, когда другой поток одновременно удаляет все обработчики событий между вашими 'if' и вызовом события. –

+0

... Или заблокировать (MyEvent()), прежде чем оценивать значение if и освободить его потом. Вопрос состоял только в том, чтобы поднимать событие, и это то, на что я ответил; если он присоединяет и отвлекает обработчиков волей-неволей, это указывает на более продвинутое знание событий в целом, исключая необходимость задать вопрос. – KeithS

+0

Вы правы в принципе, но это не то, что я имею в виду: копирование события на местном уровне является прочной практикой. * No * код повышения событий никогда не должен быть написан без него, даже не в качестве примера (поскольку, если вы не ожидаете многопоточной проблемы, вы не будете думать об этом). Прикрепление событий nilly-willy - это не то, что может контролировать пользовательский код управления - это зависит от пользователя. В качестве кода многократного использования код управления пользователя должен быть максимально прочным. –

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

Просто уточнить, поскольку я, возможно, неправильно понял вопрос. Вы ищете «Enter» специально или пытаетесь захватить отправку через TextBox? –

1

Обычно invokation событие завернутые в метод с именем что-то вроде "О [EventName]", который подтверждает что у дельгата есть одна или несколько целей (событие не равно null), а затем вызывает его с отправителем и любым применимые аргументы ... так что-то, как это типичная картина:

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 
     } 

Я надеюсь, что это было полезно для вас.

Смежные вопросы