C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: イベントを自分で発生させるやりかた


(過去ログ 97 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■57913 / inTopicNo.1)  イベントを自分で発生させるやりかた
  
□投稿者/ めめ (21回)-(2011/03/22(Tue) 11:51:43)

分類:[C#] 

2011/03/22(Tue) 11:52:16 編集(投稿者)

こんにちは。
C#のイベントについて質問です。

私は以下のように、フォームにテキストボックスを配置して、テキストボックスにTextChangedのイベントを追加しました。

textBoxKey.TextChanged += new EventHandler(textBox_TextChanged_InputCheck);

private void textBox_TextChanged_InputCheck(object sender, EventArgs e)
{
TextBox box = (TextBox)sender;
if (box.Text == string.Empty) box.BackColor = ColorPicker.error;
else box.BackColor = ColorPicker.normal;
}

このメソッド自体は適切に動作しているのですが、フォームを表示した時のイベント(Shown)で、
同様のイベントをプログラム上から手動で実行したいですが、
“もっとも適切な”イベントを実行する書き方が分からなくて困っています。

AS3のイベントでは、メソッドを直接書かずに以下のようにすると思います。
[object].dispatchEvent([event]);

C#でも似たようなアプローチをして、イベントを実行するものなのでしょうか?
それとも、ベタにメソッドを呼び出すコードを書くのでしょうか?
一応自分でも調べたのですが、RaiseEventがそれと対応するもののように思ったのですが、
うまく動かすことができなかったです。

以上です、よろしくお願いします。


参考
http://msdn.microsoft.com/ja-jp/library/fwd3bwed.aspx
(Raiseイベント)


引用返信 編集キー/
■57914 / inTopicNo.2)  Re[1]: イベントを自分で発生させるやりかた
□投稿者/ shu (529回)-(2011/03/22(Tue) 12:17:29)
No57913 (めめ さん) に返信

やりたいことがいまいち分かりませんが、

Showのイベントを割り当てたければ

this.Shown += new EventHandler(Fom1_Shown);

このようにすればいいかと。


引用返信 編集キー/
■57915 / inTopicNo.3)  Re[2]: イベントを自分で発生させるやりかた
□投稿者/ マサヤ (289回)-(2011/03/22(Tue) 12:22:29)
>フォームを表示した時のイベント(Shown)で、
>同様のイベントをプログラム上から手動で実行したい
→よくわかりません、画面初期にて
box.BackColor = ColorPicker.error;
else box.BackColor = ColorPicker.normal;
こうしたいということですか?

イベントの登録は、画面のプロパティから使用したいイベントを選択してダブルクリックすると簡単ですよ。
引用返信 編集キー/
■57916 / inTopicNo.4)  Re[3]: イベントを自分で発生させるやりかた
□投稿者/ みきぬ (956回)-(2011/03/22(Tue) 12:30:19)
本当にやりたいことは TextChanged イベントを発生させることではなく、
TextChanged のイベントハンドラ内でおこなっている処理を実行することではないでしょうか。

そうであれば、TextChanged のイベントハンドラでおこなっている処理をそのまま別メソッドにしてしまい、
Shown イベントハンドラからそのメソッドを呼べばよいでしょう。
引用返信 編集キー/
■57918 / inTopicNo.5)  Re[4]: イベントを自分で発生させるやりかた
□投稿者/ マサヤ (290回)-(2011/03/22(Tue) 12:58:11)
delegate void DelTest(object sender);
    class TestClass
    {
        public void TestMethod(object sender)
        {
            TextBox txt = (TextBox)sender;
            if (String.IsNullOrEmpty(txt.Text))
                txt.BackColor = ColorPicker.error;
            else
                txt.BackColor = ColorPicker.normal;
        }
    }

private void textBox1_TextChanged(object sender, EventArgs e)
        {
            TestClass tc = new TestClass();
            DelTest test = new DelTest(tc.TestMethod);
            test(textBox1);
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            TestClass tc = new TestClass();
            DelTest test = new DelTest(tc.TestMethod);
            test(textBox1);
        }
こんな感じでいかがですか?

引用返信 編集キー/
■57919 / inTopicNo.6)  Re[5]: イベントを自分で発生させるやりかた
□投稿者/ todo (128回)-(2011/03/22(Tue) 13:10:29)
> “もっとも適切な”イベントを実行する書き方が分からなくて困っています。

Relectionを使って無理やりですが..

MethodInfo m = typeof(TextBox).GetMethod("OnTextChanged", BindingFlags.NonPublic | BindingFlags.Instance);
m.Invoke(textBox1, new object[] { EventArgs.Empty });
引用返信 編集キー/
■57924 / inTopicNo.7)  Re[6]: イベントを自分で発生させるやりかた
□投稿者/ PATIO (97回)-(2011/03/22(Tue) 15:12:23)
私もみきぬさんの提案に賛成です。

必要な処理を別メソッドにしてしまってそれを両方のイベントから呼ぶようにした方が
スマートな気がします。両方のイベントから呼びたいという部分がはっきりしていれば、
その共通で呼ばれるメソッドのインターフェイスも自ずと決まると思います。

引用返信 編集キー/
■57925 / inTopicNo.8)  Re[6]: イベントを自分で発生させるやりかた
□投稿者/ めめ (22回)-(2011/03/22(Tue) 15:15:39)

shuさん,マサヤさん
具体的なコードを書かずにイベントを手動で実行したいだけです。

うまく説明できなくて、もどかしい感じでもうしわけないです。
イベントを追加するのでも、具体ソースを書くのでもなくAS3のdispachEventみたいなことが可能なのかが気になっています。


みきぬさん
> 本当にやりたいことは TextChanged イベントを発生させることではなく、
> TextChanged のイベントハンドラ内でおこなっている処理を実行することではないでしょうか。

その通りです。
ただ、その場合も初期化の時だけメソッド名を直に呼び出すのではなく、
細かい差ですが、イベント経由で呼ぶほうがメンテナンス性がよいと思いました。


マサヤさん
なるほど、委譲で解決するのですね。
直接呼び出すのとイベントを自分で始動させるパターンの、折中案のように見えます。
現地点ではもっともソース的にいいように思えました。


todoさん
こういう解決策を期待していました…が、予想以上に周りくどいのですね。
メンテナンス性もよいとは言えないように見えますし……。どうしたものか。


私はどれだけソースを書くのが遅くなってもメンテナンス重視でコーディングしたいと思っているのですが、
どの意見がもっともメンテナンス性とコード的に美しいのでしょうか?

1.マサヤさんのパターン 委譲経由で呼び出し
2.todoさんのパターン Relectionで呼び出し
3・みきぬさんのパターン メソッドでカプセル化

ケースバイケースで異なるとは思うのですが、
今回は画面表示した時に、テキストボックスは値渡しがあったりなかったりするのがキーです。

初期状態(空欄)のままだと、テキストボックスが赤くするのが仕様です。
しかし、入力必須チェックなだけなので、仕様変更になる可能性も高いです。

そこで私は、なるべく柔軟に設計して修正箇所を後々少なくしておきたいです。(幅広いコンポーネントなので)
メソッド呼び出しだと、どうしてもメソッド名の変更が必要になることもあるかと思えるので、
委譲とRelectionが私にはよい解決案のように見えていますが……間違っているでしょうか。


以上です、よろしくお願いします。

引用返信 編集キー/
■57929 / inTopicNo.9)  Re[7]: イベントを自分で発生させるやりかた
□投稿者/ shu (531回)-(2011/03/22(Tue) 15:36:59)
No57925 (めめ さん) に返信

> shuさん,マサヤさん
> 具体的なコードを書かずにイベントを手動で実行したいだけです。
何にしても、
this.Shown += new EventHandler(Fom1_Shown);

は必要ですよ?(マサヤさんの言うようにプロパティ画面からのイベントダブル
クリックで自動でコード生成は出来ますが。)


> 
> うまく説明できなくて、もどかしい感じでもうしわけないです。
> イベントを追加するのでも、具体ソースを書くのでもなくAS3のdispachEventみたいなことが可能なのかが気になっています。
AS3が分からないのでこれが何なのか分からなくてすみません。

こんなんでどう?


this.Shown += new EventHandler(Fom1_Shown);
textBoxKey.TextChanged += new EventHandler(textBox_TextChanged);  //<--- Validating,Validatedとかの方がいいかも

・・・


private void Fom1_Shown(〜)
{
    CheckEntry(null);
}


private voiid textBox_TextChanged(〜)
{
    CheckEntry(〜);
}

private ??? CheckEntry(〜)    //<--- ???は戻り値で何か行う場合、その型を指定
{
   //ここに各項目のチェック処理を集約
}


引用返信 編集キー/
■57930 / inTopicNo.10)  Re[7]: イベントを自分で発生させるやりかた
□投稿者/ ピューロ (1回)-(2011/03/22(Tue) 15:40:57)
> メソッド呼び出しだと、どうしてもメソッド名の変更が必要になることもあるかと思えるので、
なぜメソッド名が変更になる可能性があるの?
公開メンバならいざ知らず、privateなメソッドならメソッド名はどうでもいいはず。

みきぬさん案の、各イベントからメソッドを呼び出すのが一番分かりやすくてメンテナンス性が高いと思うが。
例えば、他の人がメンテナンスを行う必要があるならばなおさらだ。
美しさも求めているようで、何を目指しているのか分からないが、シンプルなのが一番ではないか?
引用返信 編集キー/
■57933 / inTopicNo.11)  Re[7]: イベントを自分で発生させるやりかた
□投稿者/ PATIO (99回)-(2011/03/22(Tue) 15:49:35)
メンテナンス性と言う部分をどう考えるかと言う話になると思いますが、

共通のメソッドを起こして両方から呼ぶのは良くないと言う話なら
delegateを使ったやり方の方が良いのではと言う気がします。
(個人的にはメソッド名を工夫するとか、リファクタリングの機能で
対応可能な気もするのでそこまで大きな問題ではないようにも感じますが)

無理にイベントを起こして処理を実行させるという方法だと
本来のTextChangedイベントとは意味が違う使い方になってしまうと思うので
イベントの意味付けからするとやはり自然ではない気がします。
delegateを使うとコード量が増えてしまうのは確かですけれど。

メソッドの意味付けに沿った使い方をした方が後でコードを見た時に
理解しやすいのではと言う気がします。

引用返信 編集キー/
■57954 / inTopicNo.12)  Re[8]: イベントを自分で発生させるやりかた
□投稿者/ めめ (23回)-(2011/03/22(Tue) 17:57:13)

shuさん
サンプルありがとうございます。
みきぬさん案のメソッド解決のやり方ですね。
これも悪い解決策だとは思っていません。
ただ、イベント自体を自分のソースコードでイベントを発生させられるのか?
それを起こせるなら、どちらがよりC#らしい書き方なのかといろいろ教えてもらってました。


ピューロさん
シンプルなのがいい、というのはそうですね。
ただ、そのシンプルという考え方が、C#ではどうするべきなのか私の中でまとまっていません。
delegate然り、C#ならよりシンプルになるというケースがまだまだ分からなかったのです。

美しい書き方というのは書き方が悪かったですね、すいません。
私はどうするのが、C#のイベントで“もっとも適切な”やり方なのか知りたいです。

私はC#が不勉強なのもあり、特にC#でのイベントは不慣れです。
細かい話ですが、イベントに対して変なアプローチをかけていないか、それが気になっての追加の質問でした。


PATIOさん
> 本来のTextChangedイベントとは意味が違う使い方になってしまうと思うので
> イベントの意味付けからするとやはり自然ではない気がします。
自分にもわかりやすい理由で納得できました。その通りだと思えました。
Delegateを利用するのは、ちょっと構えすぎた対応かもしれないということですね。

全体通して、
C#にはAS3のdispatchEvent的なものは、回りくどくて良くないというのが分かりました。
無理なイベント発生とも捉えることができるので、ソースの流れの上で意味づけが出来ず良くない。

また、イベントでも初期化でも普通にメソッドで機能をカプセルにしておくのがいいというのも分かりました。
これはC#のイベントに対して過剰に構えていたのかもしれません。意図が分からず、混乱した方々すいません。

委譲を通した考え方も出してもらって、C#のいろいろな書き方が分かってとてもよかったです。
納得のいく説明をいくつも頂けたので解決とします。

また、何か勘違いしてるとか、補足などあればご意見頂けると幸いです。
回答者の方々、ありがとうございました。


解決済み
引用返信 編集キー/
■57991 / inTopicNo.13)  Re[9]: イベントを自分で発生させるやりかた
□投稿者/ くり太郎 (7回)-(2011/03/23(Wed) 13:46:18)
くり太郎 さんの Web サイト
No57954 (めめ さん) に返信
> また、何か勘違いしてるとか、補足などあればご意見頂けると幸いです。

補足です。

C# のイベントは、オブザーバーパターンというデザインパターンに準じて設計されていて、デリゲートの仕組みを使って実現しています。
以下のコードがオブザーバーに、イベントハンドラーを登録している部分にあたります。

textBoxKey.TextChanged += new EventHandler(textBox_TextChanged_InputCheck);

上記は、EventHandler オブジェクトを生成後に、textBoxKey オブジェクトの TextChanged イベントに、そのオブジェクトを追加していることになります。

EventHandler オブジェクトでは、textBox_TextChanged_InputCheck というメソッドが指定されているため、このイベントが発生したとき、textBox_TextChanged_InputCheck メソッドが呼び出されます。
これは、EventHander というデリゲート型に、textBox_TextChanged_InputCheck メソッドを割り当てたことと同じ意味を持ちます。

ここで使用されている += 演算子が、TextChanged イベントに EventHander 型オブジェクトを追加しています。
これは、複合演算子をオーバーロードしていて、内部的には TextChanged イベントのコレクションにイベントハンドラを追加するといった動きをしています。

private void textBox_TextChanged_InputCheck(object sender, EventArgs e)
{
}

これはイベントハンドラーとして登録されているメソッドですが、これは EventHander 型に準じた戻り値の型とシグニチャを持ったメソッドの必要があります。
EventHander 型は自作することで、イベント発生時に値を受け取ることもできますが、第2引数は、EventArgs 型を継承している必要があります。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -