Подтвердить что ты не робот

Наследование обработчиков событий в С#

Я вроде как поддержал себя в углу здесь.

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

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

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

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

4b9b3361

Ответ 1

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

base.checkReadyness(sender, e);

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Убедитесь, что это то, что происходит. HTH:)

Ответ 7

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

Ответ 8

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

Ответ 9

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

        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, но он отлично подходит для меня даже без проверки.