新規イベントの実装
前景色が変更された時に呼び出される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
2014年1月3日