2

C# では、OnClick、OnExit などの保護された仮想メソッドを介して、所有するクラスによってのみイベントを発生させることができます。私がやろうとしているのは、いくつかの複雑なクラスに GOF 状態パターンを実装することです。状態クラスから所有クラスのイベントを発生させる方法が見つからないことを除いて、これまでのところすべてうまくいきました。

たとえば、私のボタンには 2 つの状態 (アップとダウン) があり、DownState クラスはユーザー入力をチェックし、必要に応じてボタンの Click イベントを発生させます。

public class Button
{
    public Button()
    {
        State = new ButtonStateNormal(this);
    }

    public event EventHandler<MouseEventArgs> Click;
    public ButtonState State { get; set; }

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

public class ButtonStateNormal : ButtonState
{
    Button button;
    public ButtonStateNormal(Button button)
    {
        this.button = button;
    }

    public override void CheckForInput()
    {
        //...
        //Check for user input and change the state
        //...
        button.State = new ButtonStateDown(button);
    }
}

public class ButtonStateDown : ButtonState
{
    Button button;
    public ButtonStateDown(Button button)
    {
        this.button = button;
    }

    public override void CheckForInput()
    {
        //...
        //Check for user input, fire the event of the button and change the state
        //...
        button.OnClick(new MouseEventArgs(mouse.X, mouse.Y)); //I want to do this, obviously it won't work this way
        button.State = new ButtonStateNormal(button);
    }
}

どうやってやるの?

4

1 に答える 1

2

ButtonStateクラスにイベントまたはデリゲートを設定して、ボタンで呼び出すことができるようにします。自動StateプロパティをButton、状態が変更されるたびに this イベントまたはデリゲートをフックおよびアンフックするバッキング ストアを持つものに変更します。

public class Button
{
    public Button()
    {
        State = new ButtonStateNormal(this);
    }
    private ButtonState _state;
    public event EventHandler<MouseEventArgs> Click;
    public ButtonState State
    {
        protected get
        {
            return _state;
        }
        set
        {
            if (_state == value)
                return;
            if (_state != null)
                _state.Click -= OnClick;
            if (value != null)
                value.Click += OnClick;

            _state = value;

        }
    }

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

    public void CheckForInput(){
        State.CheckForInput();
    }
}

public abstract class ButtonState
{
    public abstract void CheckForInput();
    public ClickDelegate Click;
    public delegate void ClickDelegate(MouseEventArgs a);
}

そして、具体的な State クラスでこれを行うことができます

public class ButtonStateDown : ButtonState
{
    Button button;
    public ButtonStateDown(Button button)
    {
        this.button = button;
    }

    public void CheckForInput()
    {
        //...
        //Check for user input, fire the event of the button and change the state
        //...
        if(Click != null)
            Click(new MouseEventArgs(mouse.X, mouse.Y))
        button.State = new ButtonStateNormal(button);
    }
}
于 2013-03-09T04:46:05.997 に答える