web-dev-qa-db-ja.com

C#でユーザーコントロールにイベントを追加する方法

3つのラベルを含むUserControlがあります。ラベルの1つのテキストが変更されたときに発生するイベントを追加したいと思います。
私はVisual Studio 2010を使用しています

26
Saeed

まず、クラス内で(メソッドとコンストラクターとともに)イベントを宣言する必要があります。

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;

        ...
    }
}

ここ は、さらに読むためのイベント設計に関するフレームワーク設計ガイドラインです。

52
Zach Johnson

最初に、たとえばユーザーコントロールでイベントを宣言する必要があります。

public event EventHandler TextOfLabelChanged;

次に、実行時にイベント(存在する場合)にバインドされているコールバック関数を呼び出す必要があります。これを行うには、次のようなラベルのTextChangedイベントを処理します。

public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}

必要に応じて、独自のEventArgsオブジェクトを作成できます。

コードのどこかに、次のようにラベルのTextChangedイベントをこのメソッドにバインドする必要があります。

_myLabel.TextChanged+=LabelTextChanged;
3
Beatles1692

コンパイルエラー。2行目に「予期されたクラス、デリゲート、列挙型、インターフェース、または構造体」とあり、「イベント...に問題があるようです。


これらの2行は、クラス宣言内にある必要があります。

public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;
1
Vince

それを行うには非常に簡単な方法があります!

UserControlフォーム:

  1. プロパティをパブリックに変更して、どこからでもアクセスできるようにする

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
 }
1
Arsalan

event内でdelegateおよびNamespaceを宣言する必要があります。コードをclassスコープ内に移動してください。正常に動作します。

0
prem
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);
    }
}
0
thelost