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

Вызов событий С# из-за пределов собственного класса?

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

myCustomGUIElement.Click(sender,args);

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

myCustomGUIElement.Click = null;

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

Ответ 3

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

Ответ 4

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

public event Action<int> RecipeSelected;
public void RaiseRecpeSelected(int recipe) => RecipeSelected?.Invoke(recipe);