3つのラベルを含むUserControlがあります。ラベルの1つのテキストが変更されたときに発生するイベントを追加したいと思います。
私はVisual Studio 2010を使用しています
まず、クラス内で(メソッドとコンストラクターとともに)イベントを宣言する必要があります。
public event EventHandler LabelsTextChanged;
次に、個々のラベルのTextChanged
イベントを処理するメソッドを作成する必要があります。
private void HandleLabelTextChanged(object sender, EventArgs e)
{
// we'll explain this in a minute
this.OnLabelsTextChanged(EventArgs.Empty);
}
どこか、おそらくコントロールのコンストラクタ内で、ラベルのTextChanged
イベントをサブスクライブする必要があります。
myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;
次に、HandleLabelsTextChanged
メソッドについて説明します。 LabelsTextChanged
を直接調達できます。ただし、.NETフレームワーク設計ガイドラインでは、OnEventName
で保護された仮想メソッドを作成してイベントを発生させることがベストプラクティスであるとしています。このようにして、継承クラスはOnEventName
メソッドをオーバーライドすることでイベントを「処理」できます。これにより、イベントのサブスクライブよりもパフォーマンスが少し向上します。 OnEventName
メソッドをオーバーライドしないと思う場合でも、イベント発生プロセスを簡略化するため、とにかくそれを行う習慣をつけることをお勧めします。
これがOnLabelsTextChanged
です。
protected virtual void OnLabelsTextChanged(EventArgs e)
{
EventHandler handler = this.LabelsTextChanged;
if (handler != null)
{
handler(this, e);
}
}
サブスクライバーのないイベントはnullであるため、nullを確認する必要があります。 nullイベントを発生させようとすると、NullReferenceException
が返されます。イベントのEventHandler
をローカル変数にコピーしてから、nullをチェックしてイベントを発生させることに注意してください。代わりに次のようにした場合:
if (this.LabelsTextChanged != null)
{
this.LabelsTextChanged(this, e);
}
無効性チェックとイベント発生の間には競合状態があります。イベントが発生する直前にイベントのサブスクライバーがサブスクライブを解除したが、nullをチェックした後で例外がスローされた場合、通常、この問題は発生しませんが、安全な方法で書く習慣を身に付けることをお勧めします。
編集:これがpublic event EventHandler LabelsTextChanged;
行を配置する必要があります:
namespace YourNamespace
{
class MyUserControl : UserControl
{
// it needs to be here:
public event EventHandler LabelsTextChanged;
...
}
}
ここ は、さらに読むためのイベント設計に関するフレームワーク設計ガイドラインです。
最初に、たとえばユーザーコントロールでイベントを宣言する必要があります。
public event EventHandler TextOfLabelChanged;
次に、実行時にイベント(存在する場合)にバインドされているコールバック関数を呼び出す必要があります。これを行うには、次のようなラベルのTextChangedイベントを処理します。
public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}
必要に応じて、独自のEventArgsオブジェクトを作成できます。
コードのどこかに、次のようにラベルのTextChangedイベントをこのメソッドにバインドする必要があります。
_myLabel.TextChanged+=LabelTextChanged;
コンパイルエラー。2行目に「予期されたクラス、デリゲート、列挙型、インターフェース、または構造体」とあり、「イベント...に問題があるようです。
これらの2行は、クラス宣言内にある必要があります。
public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;
それを行うには非常に簡単な方法があります!
UserControlフォーム:
userControlを使用しているメインフォーム上:
.5:using
リージョンにusing userControl1=UserControl.userControl1
を追加します
1. 'Laod'イベントをUserControlに追加します。
this.userControl1.Load += new System.EventHandler(this.userControl1_Load);
2. userControl1_Loadで:
private void userControl1_Load(object sender, EventArgs e)
{
(sender as UserControl1).label1.TextChanged += label1_TextChanged;
//add a 'TextChanged' event to the label1 of UserControl1
OR use direct cast:
((UserControl1) sender).label1.TextChanged += label1_TextChanged;
}
3. in label1_TextChanged:
private void label1_TextChanged(object sender, EventArgs e)
{
//do whatever you want
}
event
内でdelegate
およびNamespace
を宣言する必要があります。コードをclass
スコープ内に移動してください。正常に動作します。
public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;
// ...
protected void MyTextBox_TextChanged(object sender, EventArgs e)
{
if (LabelTextChanged != null) {
LabelTextChanged(this, e);
}
}