2011-01-27 18 views
14

私は、ボタンをクリックすると、2つのオブジェクトをメソッドに渡すことができる必要があります。私はこれをどのようにして行うのですか?ボタンイベントメソッドに変数を渡すにはどうすればいいですか?

は、これまでのところ私は、変更のEventArgsを作成する時に見てきた:

public class CompArgs : System.EventArgs 
    { 
    private object metode; 
    private Type typen; 

    public CompArgs(object m, Type t) 
    { 
     this.metode = m; 
     this.typen = t; 
    } 

    public object Metode() 
    { 
     return metode; 
    } 

    public Type Typen() 
    { 
     return typen; 
    } 
} 

しかし、どのように私はそれを使用するのでしょうか?何らかの形でボタンのクリックイベントをオーバーライドして、カスタムイベントハンドラを使用することは可能ですか?これは、CompArgをパラメータとして使用しますか?

private void button1_Click(object sender, EventArgs e) 
     { 


      Assembly assembly = Assembly.LoadFile(@"c:\components.dll"); 

      int counter = 0; 

      foreach (Type type in assembly.GetTypes()) 
      { 
       if (type.IsClass == true) 
       { 

        Button btn = new Button(); 
        btn.Location = new Point(174 + (counter * 100),10); 
        btn.Size = new Size(95, 23); 
        btn.Name = type.Name; 
        btn.Text = type.Name; 
        btn.UseVisualStyleBackColor = true; 


        this.Controls.Add(btn); 

        object obj = Activator.CreateInstance(type); 

        //I need to pass on obj and type to the btn_Click 
        btn.Click += new eventHandler(btn_Click); 

        counter++; 
       } 
      } 
     } 

と私はそれを必要とするイベント-方法:

private void btn_Click(object sender, CompArgs ca) 
     { 
       MessageBox.Show((string)ca.Typen().InvokeMember("getMyName", 
          BindingFlags.Default | BindingFlags.InvokeMethod, 
          null, 
          ca.Metode(), 
          null)); 

     } 
+0

あなたがButtonクラスから派生させてのOnClickメソッドをオーバーライドすることができます。このテクニックを使って答えを加えました。 – Ian

答えて

5

カント撮影しているときに発生するイベントを作成することができますまたはボタンをホストし、ボタンのクリックイベントからこれらにアクセスするフォーム上のメンバ変数?

EDIT:フィードバックコメント(ない上記と同じ提案)した後、カスタムボタンクラスの提案は

class MyButton : Button 
{ 
    private Type m_TYpe; 

    private object m_Object; 

    public object Object 
    { 
     get { return m_Object; } 
     set { m_Object = value; } 
    } 

    public Type TYpe 
    { 
     get { return m_TYpe; } 
     set { m_TYpe = value; } 
    } 
} 




Button1Click(object sender, EventArgs args) 
{ 
    MyButton mb = (sender as MyButton); 

    //then you can access Mb.Type 
    //and Mb.object 
} 
+1

@WraithNath - これまではこのアプローチを使用しましたが、それを行うには不正な方法だと感じています。私は、最後の時間にオブジェクトをリストに格納する方法でしたので、正しいオブジェクトを参照するためのボタンが必要です。 Buttonオブジェクトの相対インデックスをTagプロパティに保存し、必要なときにそれを解析します。 – Bildsoe

+0

こんにちは、クリックイベントに渡す情報がどこから来ていますか?既にフォーム上にあるボタンコントロール内に存在しますか?ボタンクリックハンドラを変更できる唯一の方法は、独自のボタンコントロールまたはWindowsフォームの派生オブジェクトを実装することです。クリックイベントで使用するオブジェクトをボタンのタグに配列またはカスタムタイプとして格納し、送信側をボタンとしてキャストしてタグを取得することができます。ボタンは、ユーザーが選択してオプションを選択してフォームを閉じるポップアップフォーム上にありますか? – WraithNath

+0

@WraithNath - 私はいくつかのコードを追加しました。あなたが説明するコンセプトは、私がそれを以前にどのように扱ったかです。しかし、私が言ったように、それは少し汚れていると感じます。 – Bildsoe

1

あなたが事前に定義されたイベントハンドラの署名のために、独自のカスタムイベント引数クラスを使用することはできません。少なくともカスタムイベントの引数型は、ハンドラへのデフォルトの呼び出し(ボタンの場合にはEventArgsになります)によって決して利用されることはありません。カスタムタイプを渡してハンドラを呼び出すこともできますが、EventArgsからキャストしたものにキャストするためにはロジックが必要です。

可能な解決策として、イベントの引数型と同様に、必要な項目をカプセル化する複合型を考慮しますが、イベント内から利用できるアクセス可能な変数として必要なインスタンスを保持します少なくとも偶数ハンドラが呼び出すメソッドによって呼び出されます。例えば

、あなたのタイプを定義...

public class MyType 
{ 
    public object AccessibleItem { get; set; } 
} 

そして、あなたのフォームクラスで...

private MyType MyTypeInstance = new MyType(); 

private void Button_Click(object sender, EventArgs e) 
{ 
    //here we can set the item, if needs be... 
    MyTypeInstance.AccessibleItem = new Anything(); 
    //or access the item to use as required... 
    DoSomeMagicWithMyObject(MyTypeInstance.AccessibleItem); 
} 

EDIT:

さて、私はあなたの現在のコードを見て(これはフォームコントロールコンテナに項目を追加するのではなく、Linq内で可変イテレータを使用しています(これは私が思っているか、まさに右下の間違っているか(?)、しかしちょっと.. 。):

private void BuildButtonToObjectDictionary() 
    { 
     int counter = 0; 
     var assembly = Assembly.LoadFile(@"c:\components.dll"); 

     var buttonToObjectDictionary = (
      from type in assembly.GetTypes() 
      where type.IsClass && !type.IsAbstract 
      select new 
      { 
       Button = new Button 
       { 
        Name = type.Name, 
        Text = type.Name, 
        Size = new Size(95, 25), 
        Location = new Point(175 + (counter * 100), 10), 
        UseVisualStyleBackColor = true 
       }, 
       Item = Activator.CreateInstance(type), 
       Index = counter++ 
      }); 
    } 
+0

しかし、私は自分のオブジェクトがアクセスされる必要があるたくさんのボタンを持っています。これどうやってするの。以前私はリストにオブジェクトを格納しました。 Buttonオブジェクトの相対インデックスをTagプロパティに保存し、必要なときにそれを解析します。 – Bildsoe

+0

@Bildsoe:インスタンスはどこに作成されますか? ITは同じ種類のコンセプトですが、 'Key'はボタンを参照し、適切な' Value'や 'Hashtable'と関連している' Dictionary'を使うことができます。 –

+0

私は何を達成しようとしているかを示すためにいくつかのコードを追加しました。 – Bildsoe

0

は、より良い答えを与えるために多くのコードを参照する必要がありますが、あなたは、パラメータとしてあなたCompArgsを取り、buttonEventは、あなただけのプロパティを設定し

0

開くyourForm.Designer.csが提出した場合、あなたは、VSによって生成されたすべてのコードの自動表示されますここでは、ボタンをクリックしたときに呼び出されるメソッドを変更できます(または2番目のメソッドを追加することもできます)。

this.yourButton.Location = new System.Drawing.Point(211, 51); 
this.yourButton.Name = "yourButton"; 
this.yourButton.Size = new System.Drawing.Size(75, 23); 
this.yourButton.TabIndex = 0; 
this.yourButton.Text = "yourButton"; 
this.yourButton.UseVisualStyleBackColor = true; 
this.yourButton.Click += new System.EventHandler(this.yourMethodHere(object1, object2); 

これが役に立ちます。

+0

これは可能ですか?送信者ではなく、eventArgsは常にパラメータとして渡されますか? – Bildsoe

+1

私が見る限り、これはまったく動作しません。そして、たとえそれがあったとしても、呼び出されるのではなく、パラメータとして指定された同じ2つの引数と、呼び出しごとに指定された引数があります。そして、それが望ましい動作になった場合、カッコがないためにコンパイルされません。 –

2

これがWinformsに存在するかどうかはわかりませんが、WPFではわかりません。オブジェクトを添付できるすべてのコントロールに「タグ」オブジェクトがあります。渡すオブジェクトを保存して、イベントハンドラでそれを送信者オブジェクトから読み戻すことができます。

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    var note = (sender as FrameworkElement).Tag as Note; 
    //Do something with note here 
} 
+0

Winformsと同じです – flq

+1

これは非常にエレガントな方法ではありません。あなたはタグについて知っていなければなりません。 – Ian

3

私は新しいボタンを作成し、OnClickメソッドをオーバーライドします。 EventArgsを渡すのではなく、追加のメンバーで新しい派生クラスを渡します。

イベントを受け取るデリゲートで、取得する予定の派生クラスにEventArgsをキャストするか、またはボタンを押したときに同時にトリガーされる新しいイベントを設定し、それに接続します代わりに物事をより暗黙的にする。

コード例:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     ButtonEx b1 = new ButtonEx(); 
     b1.OnCustomClickEvent += new ButtonEx.OnCustomClickEventHandler(b1_OnCustomClickEvent); 
    } 

    void b1_OnCustomClickEvent(object sender, ButtonEx.CustomEventArgs eventArgs) 
    { 
     string p1 = eventArgs.CustomProperty1; 
     string p2 = eventArgs.CustomProperty2; 
    } 
} 

public class ButtonEx : Button 
{ 
    public class CustomEventArgs : EventArgs 
    { 
     public String CustomProperty1; 
     public String CustomProperty2; 
    } 

    protected override void OnClick(EventArgs e) 
    { 
     base.OnClick(e); 
     if(OnCustomClickEvent != null) 
     { 
      OnCustomClickEvent(this, new CustomEventArgs()); 
     } 
    } 

    public event OnCustomClickEventHandler OnCustomClickEvent; 
    public delegate void OnCustomClickEventHandler(object sender , CustomEventArgs eventArgs); 
} 
+1

非常に良い答え –

32

うわー、君たちは完全に困難にこれを作っています。カスタムクラスやメソッドのオーバーライドは必要ありません。この例では、タブインデックス番号を渡すだけです。メソッドがその値型を期待している限り、任意のものを指定できます。

button.Click += (sender, EventArgs) => { buttonNext_Click(sender, EventArgs, item.NextTabIndex); }; 

void buttonNext_Click(object sender, EventArgs e, int index) 
    { 
     //your code 
    } 
+1

人々がなぜこの答えを使用しているのかわかりません。とても簡単です。 – Larry

+0

コントロールクラスから派生するよりもずっとエレガントで痩せています。 –

+1

ねえ、私はこれが古い投稿だと知っていますが、あなたがVS上のコードに変数を置くと、フィットがスローされます。私はkeypressでスイッチャーを送ろうと思ったボタンを持っていましたが、私は上記のコードを使っていましたが、これはブール変数のようなものではありませんでした。これはメソッドのシグネチャです: 'private void UpdateDBButton_Click(Object sender、EventArgs e 、bool fullReset) 'とイベントハンドラの行を返します:' UpdateDBButton.Click + =(sender、EventArgs)=> {bool fullReset = false; UpdateDBButton_Click(送信者、EventArgs、fullReset); }; ' –

1

ボタンのTagプロパティを使用できます。あなたは、デザイナーのプロパティウィンドウからこのプロパティに文字列値を追加し、ようにハンドラ内でそれを拾うことができます。

private void MyButton_Click(object sender, EventArgs e) 
    { 
     string tagValue = ((Button) sender).Tag; 

     if(tag == "blah") 
     { 
      // Do something 
     } 
    } 
関連する問題