Вызывать события C # извне класса-владельца?

c# events inheritance

18338 просмотра

4 ответа

Возможно ли при любых обстоятельствах добиться этого?

Мои нынешние обстоятельства таковы:

public class CustomForm : Form
{
    public class CustomGUIElement
    {
    ...
        public event MouseEventHandler Click;
        // etc, and so forth.
    ...
    }

    private List<CustomGUIElement> _elements;

    ...

    public void CustomForm_Click(object sender, MouseEventArgs e)
    {
        // we might want to call one of the _elements[n].Click in here
        // but we can't because we aren't in the same class.
    }
}

Моей первой мыслью было иметь функцию, похожую на:

internal enum GUIElementHandlers { Click, ... }
internal void CustomGUIElement::CallHandler(GUIElementHandler h, object[] args) {
    switch (h) {
        case Click:
            this.Click(this, (EventArgs)args[0]);
            break;
        ... // etc and so forth
    }
}

Это ужасно уродливый клуг, но он должен сработать ... Хотя должно быть более элегантное решение? Библиотека .NET делает это все время с обработчиками сообщений и вызывающими событиями в Control. У кого-нибудь еще есть другие / лучшие идеи?

Автор: Matthew Scharley Источник Размещён: 12.07.2019 03:34

Ответы (4)


25 плюса

Решение

Вам просто нужно добавить публичный метод для вызова события. Microsoft уже делает это для некоторых событий, таких как PerformClick для элементов управления, которые предоставляют событие Click .

public class CustomGUIElement    
{
    public void PerformClick()
    {
        OnClick(EventArgs.Empty);
    }

    protected virtual void OnClick(EventArgs e)
    {
        if (Click != null)
            Click(this, e);
    }
}

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

public void CustomForm_Click(object sender, MouseEventArgs e)        
{
    _elements[0].PerformClick();
}
Автор: Phil Wright Размещён: 20.09.2008 11:52

8 плюса

Ключевое слово события в c # изменяет объявление делегата. Он предотвращает прямое назначение делегату (вы можете использовать только + = и - = для события) и предотвращает вызов делегата извне класса.

Таким образом, вы можете изменить свой код так:

public class CustomGUIElement
{
...
    public MouseEventHandler Click;
    // etc, and so forth.
...
}

Затем вы можете вызвать событие извне класса, как это.

myCustomGUIElement.Click(sender,args);

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

myCustomGUIElement.Click = null;

что недопустимо, если делегат Click объявлен как событие.

Автор: Lee Размещён: 21.09.2008 08:56

1 плюс

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

Автор: Per Hornshøj-Schierbeck Размещён: 20.09.2008 11:52

0 плюса

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

public event Action<int> RecipeSelected;
public void RaiseRecpeSelected(int recipe) => RecipeSelected?.Invoke(recipe);
Автор: Larry Размещён: 12.07.2019 12:33
32x32