2008-09-18 3 views
12

Я вроде как поддержал себя в углу.Наследование обработчиков событий в C#

У меня есть серия UserControls, которые наследуют от родителя, который содержит несколько методов и событий, чтобы упростить ситуацию, поэтому мне не нужно писать строки и строки почти идентичного кода. Как ты делаешь. Родитель не содержит других элементов управления.

Я хочу сделать только один обработчик событий в родительском UserControl, который идет и делает вещи, которые могут выполняться только родительским элементом (то есть условным вызовом события, как определено в родительском событии) , Затем я подключил этот обработчик событий ко всем моим полям ввода в своих дочерних элемента управления, а дочерние элементы управления разобрали бы задачу разбора ввода и указав родительскому элементу, следует ли это событие выкинуть. Хороший и чистый, не повторяющийся, код для копирования-вставки (который для меня всегда приводит к ошибке).

Вот мой вопрос. Visual Studio думает, что я слишком умна наполовину и предупреждает меня, что «метод CheckReadiness» [обработчик событий в родительском] не может быть методом для события, потому что класс, из которого этот класс вытекает, уже определяет метод ». Да, Visual Studio, вот в чем дело. I хочу, чтобы у был обработчик событий, который обрабатывает события, порожденные дочерними классами, и его единственная работа заключается в том, чтобы разрешить мне подключать детей без необходимости писать одну строку кода. Мне не нужны эти дополнительные обработчики - все функциональные возможности, которые мне нужны, естественно называются детьми, которые обрабатывают ввод пользователя.

Я не уверен, почему Visual Studio начала жаловаться на это сейчас (так как это позволяло мне делать это раньше), и я не уверен, как заставить его уйти. Предпочтительно, я хотел бы сделать это без необходимости определять метод, который просто вызывает CheckReadiness. Что вызывает это предупреждение, что вызывает его сейчас, когда это произошло не час назад, и как я могу заставить его уйти, не прибегая к созданию маленьких обработчиков во всех дочерних классах?

ответ

7

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

base.checkReadyness(sender, e); 

(или его derevation) из класса ребенка. Это позволяет прогнозировать будущую эволюцию дизайна, если вы хотите сделать какой-то конкретный код проверки ошибок до вызова родительского обработчика событий. Возможно, вам не нужно будет записывать миллионы обработчиков событий, подобных этому для каждого элемента управления, вы можете просто написать его, привязать все элементы управления к этому обработчику событий, который, в свою очередь, вызовет обработчик событий родителя.

Одна вещь, которую я отметил, заключается в том, что если весь этот код помещается в DLL, тогда вы можете столкнуться с ударом производительности, пытаясь вызвать обработчик событий из DLL.

+0

Это решит проблему, но я надеялся избежать по существу пустых обработчиков ошибок, поэтому мой вопрос. – Merus 2008-09-18 07:11:33

0

Если ваше событие уже определено в вашем родительском классе, вам не нужно повторно его повторять в своем дочернем классе. Это приведет к тому, что событие будет срабатывать дважды.

Проверьте, действительно ли это происходит. HTH :)

0

Эта статья на MSDN должна быть хорошей отправной точкой: Overriding Event Handlers with Visual Basic .NET. Взгляните на . Как раздел «Ручки» может вызвать проблемы в производном классе.

+0

Это статья Visual Basic. Проблема, которую они обсуждают, не будет проблемой на C#. Это может объяснить, почему VS barfs на чем-то, что должно быть законным. – 2012-05-05 14:08:27

0

Почему бы не объявить метод как виртуальный в родительском классе, а затем вы можете переопределить его в производных классах, чтобы добавить дополнительные функции?

+0

Поэтому мне не нужно писать обработчики для каждого класса, которые идентичны. Это довольно маленькие элементы управления. Мне не нужна дополнительная функциональность. – Merus 2008-09-18 07:02:02

0

Забудьте, что это обработчик событий и просто выполняйте правильный регулярный метод переопределения в классе child.

3

Я тоже натолкнулся на это, я согласен, что похоже, что вы все делаете правильно. Объявление метода virtual - это в лучшем случае работа, а не решение.

Выполнение действительно - элемент управления, который существует только в производном классе, а производный класс присоединяет обработчик события к одному из событий этого элемента управления. Тот факт, что метод, который обрабатывает событие, определяется в базовом классе, не существует ни там, ни там, он доступен в момент привязки к событию. Событие не привязано ни к чему-то двойственному, ни к чему-то глупому, это просто вопрос, где определяется метод, который обрабатывает событие.

Определенно это не виртуальный метод - я не хочу, чтобы метод был переопределяемым производным классом. Очень расстраивает, и, на мой взгляд, ошибка в dev-studio.

1

Я только что столкнулся с точной проблемой, которую Merus первым поднял, и, как и другие, кто опубликовал ответы, я совсем не понимаю, почему VS (я теперь использую Visual C# 2010 Express) объекты с обработчиком событий определенных в базовом классе. Причина, по которой я отправляю ответ, заключается в том, что в процессе преодоления проблемы, делая код базового класса защищенным методом, который производные классы просто вызывают в своих (по существу пустых) обработчиках событий, я сделал рефакторинг переименования базы класс, и заметил, что конструктор VS перестает жаловаться. То есть, он переименовал регистрацию обработчика событий (так что он больше не соответствовал соглашению дизайнера VS о присвоении имен обработчикам событий с ControlName_EventName), и это, казалось, удовлетворяло его. Затем, когда я попытался зарегистрировать обработчик базового события (теперь переименованный) с помощью элементов управления производными классами, введя имя в соответствующем VS-событии, дизайнер создал новый обработчик событий в производном классе, который затем я удалил, оставив зарегистрированный контроль класса к методу базового класса (обработчика событий). Net, как и следовало ожидать, C# находит то, что мы хотим сделать законным. Дизайнеру VS это не нравится, когда вы следуете за соглашением об именовании обработчика событий дизайнера. Я не вижу необходимости, чтобы дизайнер работал таким образом. Anywho, время для продолжения.

0

Вот что я сделал, чтобы получить базовые методы, называемые в нескольких подобных перспективных форм, каждый из которых имеет несколько дополнительных функций, в распространенных:

 protected override void OnLoad(EventArgs e) 
    { 
     try 
     { 
      this.SuspendLayout(); 
      base.OnLoad(e); 

      foreach (Control ctrl in Controls) 
      { 
       Button btn = ctrl as Button; 
       if (btn == null) continue; 

       if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnAdd_Click); 
       else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnEdit_Click); 
       else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnDelete_Click); 
       else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnPrint_Click); 
       else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnExport_Click); 
      } 

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

Обратите внимание, что вам может потребоваться протестировать этот метод.DesignMode, чтобы вы вообще пропустили код в VS Designer, но он отлично работает для меня даже без проверки.

2

Я тоже испытал эту проблему, потому что в более ранних версиях VS вы могли «наследовать» обработчики событий. Таким образом, решение, которое я нашел без необходимости переопределять методы, - это просто назначить обработчик события где-нибудь на этапе инициализации формы. В моем случае, делается в конструкторе (я уверен, что OnLoad() будет работать, а):

public MyForm() 
    { 
     InitializeComponent(); 
     btnOK.Click += Ok_Click; 
    } 

... где обработчик Ok_Click находится в форме основания. Пища для размышлений.

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