простое пользовательское событие
Я пытаюсь узнать пользовательские события, и я пытался создать один, но кажется, что у меня есть проблема
Я создал форму, статический класс и пользовательские события. То, что я пытаюсь достичь, когда я нажимаю кнопку форма вызовет статическую функцию класса, а затем 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 мог обрабатывать событие и изменять метку.Текст
4 ответа:
Это простой способ создать пользовательские события и поднять их. Вы создаете делегат и событие в классе, из которого вы бросаете. Затем подпишитесь на событие из другой части кода. У вас уже есть пользовательский класс аргументов событий, поэтому вы можете построить на нем другие классы аргументов событий. Н. б: у меня не компилируется этот код.
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; } }
вы не создали событие. Для этого напишите:
public event EventHandler<Progress> Progress;
тогда вы можете позвонить
Progress
внутри класса, где он был объявлен как обычная функция или делегат:Progress(this, new Progress("some status"));
поэтому, если вы хотите сообщить о прогрессе в
TestClass
, событие должно быть там тоже, и оно должно быть также статическим. Вы можете подписаться на него из своей формы следующим образом:TestClass.Progress += SetStatus;
кроме того, вы должны, вероятно, переименовать
Progress
доProgressEventArgs
, так что понятно, что это есть.
как уже упоминалось, поле прогресса нуждается в ключевом слове event
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; } }
события довольно просты в C#, но документы MSDN, на мой взгляд, делают их довольно запутанными. Обычно в большинстве документов, которые вы видите, обсуждается наследование класса от
EventArgs
базовый класс и есть причина для этого. Тем не менее, это не самый простой способ сделать события, и для кого-то, кто хочет что-то быстро и легко, и во время хруста, используя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. Теперь, когда вы будете готовы, триггер (aka raise) событие где-то в вашем коде класса, например:
MyEvent("wow","this","is","cool");
конечным результатом при запуске этого является то, что консоль будет выдавать "Вау, это круто". И если вы изменили "круто" с датой или последовательностью и запустили этот триггер события несколько раз, вы увидите, что результат выйдет в последовательности FIFO, как обычно должны происходить события работать.
в этом примере я передал 4 строки. Но вы можете изменить их на любой приемлемый тип, или использовать более или менее типы, или даже удалить
<...>
out и ничего не передать обработчику событий.и, опять же, если у вас было несколько пользовательских обработчиков событий, и подписаны их все на ваше событие с
+=
оператор, тогда ваш триггер события вызвал бы их все последовательно.Идентификация Вызывающих Событий
но что делать, если вы хотите идентифицировать вызывающего это событие в обработчике событий? Это полезно, если вы хотите, чтобы обработчик событий реагировал на условия, основанные на том, кто вызвал/вызвал событие. Есть несколько способов сделать это. Ниже приведены примеры, которые показаны в порядке, как быстро они работают:
1. (Самый быстрый) Если вы уже знаете его, то передайте имя в виде литеральной строки обработчику событий при его запуске. 2. (Несколько быстро) добавьте это в ваш класс и вызовите его из вызывающего метода, а затем передайте эту строку обработчику событий при его запуске:3. (Наименее быстро, но все же быстро) в обработчике событий, когда вы запускаете его, получите строку имени вызывающего метода с этим:private static string GetCaller([System.Runtime.CompilerServices.CallerMemberName] string s = null) => s;
string callingMethod = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().ReflectedType.Name.Split('<', '>')[1];
Отписка От События
у вас может быть сценарий, в котором ваше пользовательское событие имеет несколько обработчиков событий, но вы хотите удалить один специальный из списка обработчиков событий. Для этого используйте
-=
оператора вот так:MyEvent -= MyEventHandler;
слово незначительной осторожности с этим, однако. Если вы делаете это, и это событие больше не имеет обработчиков событий, и вы снова запускаете это событие, оно вызовет исключение. (Исключения, конечно, вы можете ловить с помощью блоков try/catch.)
Очистка Всех Событий
хорошо, допустим, вы закончили с событиями, и вы больше не хотите обрабатывать. Просто установите его в null, как Итак:
MyEvent = null;
то же самое предостережение для отмены подписки событий здесь, а также. Если пользовательский обработчик событий больше не содержит никаких событий, и вы запускаете его снова, ваша программа выдаст исключение.