我正在尝试学习自定义事件,我试图创建一个,但似乎我有一个问题
我创建了一个Form,静态类和自定义事件。我想要实现的是当我按下按钮时,Form会调用静态类函数,然后func会不时地发出一个事件来报告当前状态。 Form1将监听事件是否被引发,如果是,它将更改label1的文本
这是我到目前为止所拥有的
public partial class Form1 : Form
{
public EventHandler<Progress> progress;
public Form1()
{
InitializeComponent();
progress += SetStatus;
}
private void SetStatus(object sender, Progress e)
{
label1.Text = e.Status;
}
private void button1_Click_1(object sender, EventArgs e)
{
TestClass.Func();
}
}
文件2
class TestClass
{
public static void Func()
{
//time consuming code
Report status
// time consuming code
report status
}
}
public class Progress : EventArgs
{
public string Status { get; private set; }
private Progress() {}
public Progress(string status)
{
Status = status;
}
}
现在我不明白的是,如何从TestClass中提取事件,以便Form1可以处理事件并更改label.Text
答案 0 :(得分:131)
这是一种创建自定义事件并提升自定义事件的简便方法。您在要抛出的类中创建委托和事件。然后从代码的另一部分订阅该事件。您已经有了一个自定义事件参数类,因此您可以构建它以创建其他事件参数类。 N.B:我还没有编译这段代码。
public partial class Form1 : Form
{
private TestClass _testClass;
public Form1()
{
InitializeComponent();
_testClass = new TestClass();
_testClass.OnUpdateStatus += new TestClass.StatusUpdateHandler(UpdateStatus);
}
private void UpdateStatus(object sender, ProgressEventArgs e)
{
SetStatus(e.Status);
}
private void SetStatus(string status)
{
label1.Text = status;
}
private void button1_Click_1(object sender, EventArgs e)
{
TestClass.Func();
}
}
public class TestClass
{
public delegate void StatusUpdateHandler(object sender, ProgressEventArgs e);
public event StatusUpdateHandler OnUpdateStatus;
public static void Func()
{
//time consuming code
UpdateStatus(status);
// time consuming code
UpdateStatus(status);
}
private void UpdateStatus(string status)
{
// Make sure someone is listening to event
if (OnUpdateStatus == null) return;
ProgressEventArgs args = new ProgressEventArgs(status);
OnUpdateStatus(this, args);
}
}
public class ProgressEventArgs : EventArgs
{
public string Status { get; private set; }
public ProgressEventArgs(string status)
{
Status = status;
}
}
答案 1 :(得分:19)
您尚未创建活动。要做到这一点写:
public event EventHandler<Progress> Progress;
然后,您可以在声明为正常函数或委托的类中调用Progress
:
Progress(this, new Progress("some status"));
因此,如果您想在TestClass
报告进度,那么事件也应该在那里,它也应该是静态的。您可以通过以下表单订阅它:
TestClass.Progress += SetStatus;
此外,您可能应该将Progress
重命名为ProgressEventArgs
,以便明确它是什么。
答案 2 :(得分:11)
C#中的事件非常简单,但我认为MSDN文档令人困惑。通常,您看到的大多数文档都讨论了如何使类继承自EventArgs
基类,并且 a reason 。然而,这不是制作活动的最简单方式,对于想要快速简便的人,并且在时间紧迫的情况下,使用Action
类型是你的票。
1。在class
声明后立即在课堂上创建活动。
public event Action<string,string,string,string>MyEvent;
2。在类中创建事件处理程序类方法。
private void MyEventHandler(string s1,string s2,string s3,string s4)
{
Console.WriteLine("{0} {1} {2} {3}",s1,s2,s3,s4);
}
3。现在调用类时,告诉它将事件连接到新的事件处理程序。使用+=
运算符的原因是您将特定事件处理程序附加到事件。实际上,您可以使用多个单独的事件处理程序来执行此操作,并且在引发事件时,每个事件处理程序将按照您添加它们的顺序运行。
class Example
{
public Example() // I'm a C# style class constructor
{
MyEvent += new Action<string,string,string,string>(MyEventHandler);
}
}
4。现在,当你准备就绪时,在你的类代码中的某个地方触发(也就是提升)事件,如下所示:
MyEvent("wow","this","is","cool");
运行此操作时的最终结果是控制台将发出“哇这很酷”。如果你用日期或序列改变了“酷”,并且多次运行这个事件触发器,你会看到结果出现在FIFO序列中,就像事件应该正常运行一样。
在这个例子中,我传递了4个字符串。但是你可以将它们改为任何类型的可接受类型,或者使用更多或更少的类型,甚至删除<...>
并将任何内容传递给你的事件处理程序。
而且,如果您有多个自定义事件处理程序,并使用+=
运算符将它们全部订阅到您的事件,那么您的事件触发器将按顺序调用它们。
但是,如果您想在事件处理程序中识别此事件的调用者,该怎么办?如果您希望事件处理程序根据引发/触发事件的人员的条件做出反应,这将非常有用。有几种方法可以做到这一点。以下示例按其运行速度顺序显示:
选项1.(最快)如果您已经知道它,则在触发时将名称作为文字字符串传递给事件处理程序。
选项2.(稍快)将它添加到您的类中并从调用方法调用它,然后在触发它时将该字符串传递给事件处理程序:
private static string GetCaller([System.Runtime.CompilerServices.CallerMemberName] string s = null) => s;
选项3.(最快但速度很快)在触发它的事件处理程序中,使用以下命令获取调用方法名称字符串:
string callingMethod = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().ReflectedType.Name.Split('<', '>')[1];
您可能有一个场景,其中您的自定义事件具有多个事件处理程序,但您想要从事件处理程序列表中删除一个特殊事件处理程序。为此,请使用-=
运算符,如下所示:
MyEvent -= MyEventHandler;
然而,这是一个小小的谨慎。如果您执行此操作并且该事件不再具有任何事件处理程序,并且您再次触发该事件,则会引发异常。 (例外,当然,你可以使用try / catch块进行陷阱。)
好吧,让我们说你已经完成了事件,而你又不想再处理了。只需将其设置为null,如下所示:
MyEvent = null;
此处还有对取消订阅事件的同样谨慎。如果您的自定义事件处理程序不再有任何事件,并且您再次触发它,则程序将抛出异常。
答案 3 :(得分:8)
如前所述,进度字段需要关键字事件
public event EventHandler<Progress> progress;
但我认为这不是你真正想要参加活动的地方。我想你实际上想要TestClass
中的活动。以下如何看? (我从来没有真正尝试过设置静态事件,所以我不确定以下是否会编译,但我认为这可以让你了解你应该瞄准的模式。)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TestClass.progress += SetStatus;
}
private void SetStatus(object sender, Progress e)
{
label1.Text = e.Status;
}
private void button1_Click_1(object sender, EventArgs e)
{
TestClass.Func();
}
}
public class TestClass
{
public static event EventHandler<Progress> progress;
public static void Func()
{
//time consuming code
OnProgress(new Progress("current status"));
// time consuming code
OnProgress(new Progress("some new status"));
}
private static void OnProgress(EventArgs e)
{
if (progress != null)
progress(this, e);
}
}
public class Progress : EventArgs
{
public string Status { get; private set; }
private Progress() {}
public Progress(string status)
{
Status = status;
}
}