Вызывать события C # извне класса-владельца? - PullRequest
13 голосов
/ 20 сентября 2008

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

Мои текущие обстоятельства таковы:

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. У кого-нибудь есть еще какие-нибудь / лучшие идеи?

Ответы [ 3 ]

25 голосов
/ 20 сентября 2008

Вам просто нужно добавить публичный метод для вызова события. 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();
}
8 голосов
/ 22 сентября 2008

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

Чтобы вы могли изменить свой код так:

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

Затем вы можете вызвать событие из-за пределов класса, как это.

myCustomGUIElement.Click(sender,args);

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

myCustomGUIElement.Click = null;

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

1 голос
/ 20 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...