新規イベントの実装

カスタムコントロール作成入門講座初級編

前景色が変更された時に呼び出されるForeColorChangedというイベントがあります。これと同じように、ShadowColorChangedとShadowDepthChangedというイベントを実装してみましょう。実はイベントの公開だけなら1行で済みます。クラスの行頭に次のようにイベントハンドラを加えるだけです。

public event EventHandler ShadowColorChanged;
public event EventHandler ShadowDepthChanged;
Public Event ShadowColorChanged As EventHandler
Public Event ShadowDepthChanged As EventHandler

F6キーでコンパイルしてみましょう。ShadowColorChangedとShadowDepthChangedが追加されましたね。

もちろんこのままでは、イベントは追加されても呼び出されることはありません。ShadowColorやShadowDepthが変更された時に呼び出すわけですから、それぞれのプロパティのsetの部分にコードを追加すればいいわけです。

public Color ShadowColor
{
    get {
        return _shadowColor;
    }
    set {
        _shadowColor = value;
        Invalidate();
        if (ShadowColorChanged != null)
            ShadowColorChanged(this, new EventArgs());
    }
}
Public Property ShadowColor() As Color
    Get
        Return _shadowColor
    End Get
    Set
        _shadowColor = value
        Invalidate()
        RaiseEvent ShadowColorChanged(Me, New EventArgs())
    End Set
End Property

C#の場合は、普通のメソッド呼び出しと同じように書きます。ただし、nullかどうかをチェックしなければなりません。アプリケーション側でこのイベントを使用していない場合はnullが入っているからです。

VB.NETの場合は、RaiseEventというキーワードを付けます。アプリケーション側でこのイベントを使用していない場合のチェックは自動的に行われるので必要ありません。

ところで、C#のthisやVB.NETのMeはなんなのでしょうか。すでにご存じの方も多いかもしれませんが、簡単に説明します。

アプリケーションでイベントを作成すると、次のようなコードが生成されます。

private void customControl11_ShadowColorChanged(object sender, EventArgs e)
Private Sub CustomControl11_ShadowColorChanged(sender As Object, e As EventArgs) Handles CustomControl11.ShadowColorChanged

この第一引数senderには、イベントを発生しているコントロールの実態が入っています。複数の同じコントロールを使用している場合、senderには別々の実態が入っていますね。この実態のことをクラスのインスタンスと言います。コントロール側ではこのインスタンスを指定するために、thisやMeキーワードを使うわけです。

では、第二引数のEventArgsはどうなっているのでしょうか。これには、イベントの付加情報が入っていますね。ShadowColorChangedやShadowDepthChangedでは、特に受け渡す情報がないので、”new EventArgs”で、空のEventArgsを設定しています。なお、EventArgsにはEmptyというプロパティが用意されているので、わざわざnewしなくても、”EventArgs.Empty”と書いても同じことです。

さて、ここで、なにか特別な情報を受け渡したい場合どうすればいいか、ということを考えてみましょう。そのためには、EventArgsを直接使うことはできませんから、EventArgsから派生した独自のものを作る必要があります。

ShadowDepthChangedで、変更する前の値と変更した後の値を受け渡したいとします。その場合、ClassLibrary1の外で、次のようにEventArgsから派生した独自のShadowDepthEventArgsを定義します。

public class ShadowDepthEventArgs : EventArgs
{
    public ShadowDepthEventArgs(int _oldDepth, int _newDepth)
    {
        OldDepth = _oldDepth;
        NewDepth = _newDepth;
    }
    public int OldDepth { get; set; }
    public int NewDepth { get; set; }
}
Public Class ShadowDepthEventArgs
    Inherits EventArgs
    Public Sub New(_oldDepth As Integer, _newDepth As Integer)
        OldDepth = _oldDepth
        NewDepth = _newDepth
    End Sub
    Public Property OldDepth() As Integer
    Public Property NewDepth() As Integer
End Class

イベントハンドラを呼び出す時にnewするために、2つの引数を持つコンストラクタも定義しています。

次に、ShadowDepthChangedの宣言ですが、今度は新しいイベントハンドラを使うので、まずはデリゲートを定義しなければなりません。

public delegate void ShadowDepthEventHandler(object sender, ShadowDepthEventArgs e);
public event ShadowDepthEventHandler ShadowDepthChanged;
Public Delegate Sub ShadowDepthEventHandler(sender As Object, e As ShadowDepthEventArgs)
Public Event ShadowDepthChanged As ShadowDepthEventHandler

デリゲートは、メソッドへの参照を変数に入れることを可能にするための型の定義です。イベント以外でも使われるもので、最初は理解するのが難しいかもしれませんが、まずは慣れてしまいましょう。

以上、ちょっと複雑だったかもしれませんが、イベントを呼び出す以下のコードは難しくありません。

public int ShadowDepth
{
    get
    {
        return _shadowDepth;
    }
    set
    {
        int old = _shadowDepth;
        _shadowDepth = value;
        Invalidate();
        if (ShadowDepthChanged != null)
            ShadowDepthChanged(this, new ShadowDepthEventArgs(old, _shadowDepth));
        }
}
Public Property ShadowDepth() As Integer
    Get
        Return _shadowDepth
    End Get
    Set
        Dim old As Integer = _shadowDepth
        _shadowDepth = value
        Invalidate()
        RaiseEvent ShadowDepthChanged(Me, New ShadowDepthEventArgs(old, _shadowDepth))
    End Set
End Property

これをコンパイルし、アプリケーション側でイベントを作成すると、以下のようにちゃんとShadowDepthEventArgsが使われているのがわかります。

private void customControl11_ShadowDepthChanged(object sender, ClassLibrary1.ShadowDepthEventArgs e)
Private Sub CustomControl11_ShadowDepthChanged(sender As Object, e As ClassLibrary1.ShadowDepthEventArgs) Handles CustomControl11.ShadowDepthChanged

«

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

«