39

我有一个用户控件,它在与 Web 服务通信后引发事件。父级在引发时处理此事件。我认为正确的方法是将 web 服务返回的对象作为 eventargs 传递给父对象???

如果这是正确的方法,我似乎找不到有关如何执行此操作的说明。

用户控制

public event EventHandler LoginCompleted;

然后在服务返回 biz 对象之后:

if (this.LoginCompleted != null)
        {
            this.LoginCompleted(this, new EventArgs() //this is where I would attach / pass my biz object no?);  
        }

家长

ctrl_Login.LoginCompleted += ctrl_Login_LoginCompleted;
....snip....
void ctrl_Login_LoginCompleted(object sender, EventArgs e)
    {
        //get my object returned by login
    }

所以我的问题是将用户对象返回给父对象的“批准”方法是什么?创建一个所有东西都可以访问的属性类并将其放在那里?

4

5 回答 5

48

您必须使用EventHandler<T>where Tis your class that derived from声明您的事件EventArgs

public event EventHandler<LoginCompletedEventArgs> LoginCompleted;

LoginCompletedEventArgs可能看起来像这样:

public class LoginCompletedEventArgs : EventArgs
{
    private readonly YourBusinessObject _businessObject;

    public LoginCompletedEventArgs(YourBusinessObject businessObject)
    {
        _businessObject = businessObject;
    }

    public YourBusinessObject BusinessObject
    {
        get { return _businessObject; }
    }
}

用法是这样的:

private void RaiseLoginCompleted(YourBusinessObject  businessObject)
{
    var handler = LoginCompleted;
    if(handler == null)
        return;

    handler(this, new LoginCompletedEventArgs(businessObject));
}

请注意我是如何实现RaiseLoginCompleted的。这是引发事件的线程安全版本。我消除了NullReferenceException在一个线程想要引发事件而另一个线程在if检查之后但在实际调用处理程序之前取消订阅最后一个处理程序的竞争条件场景中可能发生的可能性。

于 2013-02-20T10:48:49.483 回答
14

好吧,你可以做所有这些,或者你可以定义一个委托作为你的 EventHandler 并在它的签名中定义你的属性。

如:

public delegate void MyEventEventHandler(int prop1, string prop2, object prop3...);

public event MyEventEventHandler MyEvent;
于 2016-01-14T02:39:24.620 回答
5

我个人喜欢 Toni Petrina 的方法(参见https://coderwall.com/p/wkzizq/generic-eventargs-class)。它与公认的答案不同,因为您不必创建特殊的 EventHandler 类(例如LoginCompletedEventArgs)。

注意:我使用的是 VS 2015 和 C# v6。在旧版本的 Visual Studio 和 C# 中,您可能需要添加using System.Linq;

创建一个从 EventArgs 继承的通用 EventArgs<T> 类...

class EventArgs<T> : EventArgs {

  public T Value { get; private set; }

  public EventArgs(T val) {
     Value = val;
  }

}

声明您的事件处理程序...

public event EventHandler<EventArgs<object>> LoginCompleted;

假设您已声明并分配了一个名为 的对象loginObject,请添加代码以引发您的事件...

private void RaiseLoginCompleted() {
  if (LoginCompleted != null)
    LoginCompleted(this, new EventArgs<object>(loginObject));
}

在您的客户端代码中,添加LoginCompleted事件处理程序(使用 Linq 并调用本地方法)...

LoginCompleted += (o, e) => onLoginCompleted(e.Value); // calls a local method

void onLoginCompleted(LoginObject obj) {
  // add your code here
}
于 2018-10-04T17:00:20.770 回答
4

我建议将命名元组EventHandler<TEventArgs>.

我喜欢老狗的回答。Microsoft 已经有了这个委托EventHandler< TEventArgs >

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

您不需要继承自EventArgs.

使用命名元组声明您的事件处理程序。

public event EventHandler<(int id, string message, object LoginObject)> LoginCompleted;

在您的客户端代码中,将方法分配给 LoginCompleted 事件处理程序

选项 1:使用 lambda

LoginCompleted  += (o, e) =>
{
    Console.WriteLine($"Hello, sender is {o.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. ");
};

选项 2:调用本地方法

LoginCompleted  += onLoginCompleted;

private static void onLoginCompleted  (object sender, (int id, string message,  object LoginObject) e)
{
    Console.WriteLine($"Hello, sender is {sender.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. ");
}

我只是写了一个例子,请参考我的repo

于 2020-04-28T07:49:19.567 回答
2

有时创建一个仅将 bool 作为派生类传递的类很糟糕EventArgs!所以你可以简单地使用Action而不是EventHandler. 您可以传递任何类型和您喜欢的参数数量(Action 最多支持 16 个)。

    class Raiser
    {
        public event Action<Raiser, bool,DateTimeOffset> OnCreate;

        public void Create()
        {
            OnCreate?.Invoke(this, true,DateTimeOffset.Now);
        }
    }

    class Listener
    {
        Raiser raiser;

        public Listener()
        {
            raiser = new Raiser();
            raiser.OnCreate += Raiser_OnCreate;
        }

        private void Raiser_OnCreate(Raiser arg1, bool arg2,DateTimeOffset dateTimeOffset)
        {
            throw new NotImplementedException();//Do Your works here
        }
    }

通常 usingAction和 'Func' 比Delegate.

于 2020-01-01T12:01:58.273 回答