простое пользовательское событие

Я пытаюсь изучить пользовательские события, и я попытался создать его, но похоже, что у меня проблема.

Я создал форму, статический class и настраиваемое событие. То, что я пытаюсь достичь, – это когда я нажимаю кнопку Form, вызывается функция статического classа, а затем func будет время от времени повышать событие, чтобы сообщить текущий статус. Form1 будет слушать, если событие поднято, и если оно есть, оно изменит текст метки1

Вот что я до сих пор

public partial class Form1 : Form { public EventHandler 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

Это простой способ создать пользовательские события и поднять их. Вы создаете делегат и событие в classе, из которого вы бросаете. Затем подпишитесь на событие из другой части вашего кода. У вас уже есть собственный class аргументов аргументов, поэтому вы можете использовать его для создания других classов аргументов аргументов. NB: Я не компилировал этот код.

 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 из classа, где он был объявлен как нормальная функция или делегат:

 Progress(this, new Progress("some status")); 

Итак, если вы хотите сообщить о прогрессе в TestClass , событие должно быть там тоже, и оно также должно быть статическим. Вы можете подписаться на него в своей форме:

 TestClass.Progress += SetStatus; 

Кроме того, вы должны, вероятно, переименовать Progress в ProgressEventArgs , чтобы было ясно, что это такое.

Как уже упоминалось, в поле прогресса требуется событие ключевого слова

 public event EventHandler 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; 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, на мой взгляд, делают их довольно запутанными. Обычно большинство документов, которые вы видите, обсуждают вопрос о наследовании classа из базового classа EventArgs и есть причина для этого. Тем не менее, это не самый простой способ совершить события, а для кого-то, желающего чего-то быстрого и легкого, и во время хруста, использование типа Action – это ваш билет.

Создание событий и подписка на них

1. Создайте свое событие в своем classе сразу после объявления class .

 public event ActionMyEvent; 

2. Создайте метод classа обработчика событий в своем classе.

 private void MyEventHandler(string s1,string s2,string s3,string s4) { Console.WriteLine("{0} {1} {2} {3}",s1,s2,s3,s4); } 

3. Теперь, когда ваш class вызывается, сообщите ему, чтобы он связал событие с вашим новым обработчиком событий. Причина, по которой используется оператор += заключается в том, что вы добавляете свой обработчик события к событию. Вы можете сделать это с помощью нескольких отдельных обработчиков событий, и когда событие будет поднято, каждый обработчик событий будет работать в последовательности, в которую вы их добавили.

 class Example { public Example() // I'm a C# style class constructor { MyEvent += new Action(MyEventHandler); } } 

4. Теперь, когда вы будете готовы, запустите (ака рейз) событие где-нибудь в вашем classе, например:

 MyEvent("wow","this","is","cool"); 

Конечным результатом, когда вы запускаете это, является то, что консоль выдаст «ничего себе, это круто». И если вы изменили «круто» с датой или последовательностью и несколько раз запускали этот триггер событий, вы увидите, что результат выдается в последовательности FIFO, как обычно должны работать события.

В этом примере я передал 4 строки. Но вы можете изменить их на любой приемлемый тип или использовать более или менее типы или даже удалить <...> и ничего не передавать своему обработчику событий.

И, опять же, если у вас было несколько пользовательских обработчиков событий и подписаны все они на ваше событие с помощью оператора += , то триггер события вызвал бы их все последовательно.

Идентификация вызывающих абонентов

Но что, если вы хотите идентифицировать вызывающего абонента для этого события в обработчике событий? Это полезно, если вы хотите, чтобы обработчик событий реагировал на условия, основанные на том, кто поднял / вызвал событие. Есть несколько способов сделать это. Ниже приведены примеры, которые показывают, насколько быстро они работают:

Вариант 1. (Самый быстрый). Если вы уже знаете это, передайте имя как литеральную строку обработчику событий при его запуске.

Вариант 2. (Немного быстро) Добавьте это в свой class и вызовите его из вызывающего метода, а затем передайте эту строку обработчику события при его запуске:

 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.)

Очистка всех событий

Хорошо, допустим, вы прошли через события, и вы больше не хотите обрабатывать. Просто установите его так:

 MyEvent = null; 

Такая же предосторожность для Unsubscribing events также существует. Если ваш пользовательский обработчик событий больше не имеет каких-либо событий, и вы запускаете его снова, ваша программа выдаст исключение.

  • Как передать событие onClick для своего родителя на Android?
  • Как можно удалить все обработчики событий события «Click» кнопки «Button»?
  • Как удалить обработчик события lambda
  • Должен ли я всегда отключать обработчики событий в методе Dispose?
  • Как удалить все обработчики событий из события
  • Отслеживание положения прокрутки и уведомление об этом других компонентах
  • Передача данных между формами WinForms
  • Как проверить, была ли клавиша нажата клавишей со стрелкой в ​​Java KeyListener?
  • Каковы различия между делегатами и событиями?
  • C #: как запросить данные журнала событий с данным идентификатором события?
  • Глобальный захват клавиатуры в приложении C #
  • Interesting Posts

    Как управлять изображениями на уровне пикселей в C #

    Windows Aero автоматически переходит на базовый

    Синтаксис для однострочного бесконечного цикла Bash

    Является ли «long x = 1/2» равным 1 или 0 и почему?

    Использование Selenium Web Driver для получения значения ввода HTML

    Удаленный рабочий стол для OS X, который лучше, чем VNC?

    Подключение к удаленному URL-адресу, для которого требуется аутентификация с использованием Java

    Что делает загрузочный носитель загрузочным?

    Java-ориентированная карта / кеш с истекающими ключами

    Как оценить выражение инфикса только одним сканом с помощью стеков?

    Получите ДЛИННОСТЬ ДЛИННОГО СЫРЬЯ

    Windows 7: Событие 55 Структура файловой системы на диске повреждена и непригодна для использования

    Невозможно освободить константные указатели в C

    Как узнать, что приложение установлено из игры Google или боковой загрузки?

    Автоматическое увеличение для Oracle

    Давайте будем гением компьютера.