12

私はここで隅に追いやられました。

親から継承する一連の UserControls があります。これにはいくつかのメソッドとイベントが含まれており、単純化するため、ほぼ同一のコードを何行も記述する必要はありません。あなたのように。親には他のコントロールは含まれていません。

私がしたいのは、親 UserControl にイベント ハンドラーを 1 つだけ持つことです。これは、親コントロールだけが実行できることを行います (つまり、イベントが親で定義されているように、条件付きでイベントを呼び出します)。次に、このイベント ハンドラーを子コントロールのすべての入力ボックスに接続します。子コントロールは、入力を解析し、そのイベントをスローするかどうかを親コントロールに通知するタスクを整理します。素晴らしくきれいで、繰り返しのない、コピーアンドペーストのコード (私にとっては常にバグになります)。

これが私の質問です。Visual Studio は、私が巧妙すぎると判断し、「'CheckReadiness' メソッド [親のイベント ハンドラー] は、このクラスの派生元のクラスが既にメソッドを定義しているため、イベントのメソッドにすることはできません」と警告します。はい、Visual Studio、それがポイントです。子クラスによってスローされたイベントのみを処理するイベント ハンドラーが必要です。その唯一の仕事は、コードを 1 行も書かずに子クラスを接続できるようにすることです。これらの余分なハンドラーは必要ありません。必要なすべての機能は、子プロセスがユーザー入力を処理するときに自然に呼び出されます。

なぜ Visual Studio がこれについて不平を言い始めたのか (以前はそうさせていたので)、どうすれば解決できるのかわかりません。できれば、CheckReadiness を呼び出すだけのメソッドを定義せずに実行したいと考えています。この警告の原因、1 時間前には表示されなかったのに現在表示されている原因、およびすべての子クラスで小さなハンドラーを作成することに頼らずに、この警告を消すにはどうすればよいでしょうか?

4

9 に答える 9

7

親メソッドを仮想として宣言し、子クラスでオーバーライドして呼び出します

base.checkReadyness(sender, e);

(またはその派生) 子クラス内から。これにより、親イベント ハンドラーを呼び出す前に特定のエラー チェック コードを実行する場合など、将来の設計の進化が可能になります。コントロールごとにこのような何百万ものイベント ハンドラーを記述する必要はないかもしれません。1 つ記述するだけで、すべてのコントロールをこのイベント ハンドラーにフックして、親のイベント ハンドラーを呼び出すことができます。

私が注意したことの 1 つは、このすべてのコードが dll 内に配置されている場合、dll 内からイベント ハンドラーを呼び出そうとすると、パフォーマンス ヒットが発生する可能性があることです。

于 2008-09-18T06:57:10.687 に答える
3

私もこれに出くわしました、あなたがすべてを正しくやっているように感じることに同意します。メソッド仮想を宣言することは、せいぜい回避策であり、解決策ではありません。

実行されていることは有効です。派生クラスにのみ存在するコントロールであり、派生クラスはそのコントロールのイベントの1つにイベントハンドラーをアタッチしています。イベントを処理しているメソッドが基本クラスで定義されているという事実は、ここにもそこにもありません。イベントへのバインドの時点で使用できます。イベントは2回またはそのようなばかげたものに添付されていません。それは、イベントを処理するメソッドがどこで定義されているかという問題です。

間違いなく、これは仮想メソッドではありません。メソッドを派生クラスでオーバーライドできるようにしたくありません。非常に苛立たしく、私の意見では、dev-studioのバグです。

于 2009-02-19T14:59:58.777 に答える
2

以前のバージョンの VS では、イベント ハンドラーを「継承」できたため、私もこの問題を経験しました。したがって、メソッドをオーバーライドせずに見つけた解決策は、フォームの初期化フェーズのどこかにイベント ハンドラーを割り当てることです。私の場合、コンストラクターで行われます (OnLoad() も同様に機能すると確信しています):

    public MyForm()
    {
        InitializeComponent();
        btnOK.Click += Ok_Click;
    }

...Ok_Click ハンドラーが基本フォームに存在する場所。思考の糧。

于 2016-06-07T17:23:51.343 に答える
1

Merusが最初に提起した正確な問題に遭遇したばかりで、応答を投稿した他の人と同様に、VS(現在Visual C#2010 Expressを使用しています)オブジェクトがイベントハンドラーをベースで定義する理由がまったくわかりませんクラス。私が応答を投稿している理由は、基本クラスのコードを、派生クラスが (本質的に空の) イベント ハンドラーで単に呼び出す保護されたメソッドにすることで問題を回避する過程で、私は基本のリファクタリングの名前を変更したためです。 class メソッドを変更し、VS デザイナーが文句を言わなくなったことに気付きました。つまり、イベント ハンドラー登録の名前を変更し (そのため、ControlName_EventName を使用してイベント ハンドラーに名前を付けるという VS デザイナーの規則には従わなくなりました)、それはそれを満たしているように見えました。次に、適切な VS イベントに名前を入力して、派生クラス コントロールに対して (現在は名前が変更された) 基本イベント ハンドラーを登録しようとすると、デザイナーは派生クラスに新しいイベント ハンドラーを作成し、それを削除して、派生クラス コントロールを登録したままにしました。基本クラス (イベント ハンドラー) メソッドに。ネット、ご想像のとおり、C# は私たちがやりたいことを合法的に見つけます。デザイナーのイベント ハンドラーの命名規則に従うときに気に入らないのは、VS デザイナーだけです。デザイナーがそのように作業する必要はないと思います。とにかく、続行する時間です。C# は、私たちがやりたいことを合法的に見つけます。デザイナーのイベント ハンドラーの命名規則に従うときに気に入らないのは、VS デザイナーだけです。デザイナーがそのように作業する必要はないと思います。とにかく、続行する時間です。C# は、私たちがやりたいことを合法的に見つけます。デザイナーのイベント ハンドラーの命名規則に従うときに気に入らないのは、VS デザイナーだけです。デザイナーがそのように作業する必要はないと思います。とにかく、続行する時間です。

于 2012-03-08T16:40:58.760 に答える
0

イベントが親クラスですでに定義されている場合は、子クラスで再配線する必要はありません。これにより、イベントが 2 回発生します。

これが起こっているかどうかを確認してください。HTH :)

于 2008-09-18T06:45:58.313 に答える
0

MSDN のこの記事、「Visual Basic .NET でイベント ハンドラーをオーバーライドする」を参考にしてください。「Handles 句が派生クラスで問題を引き起こす方法」セクションを見てください。

于 2008-09-18T06:49:21.470 に答える
0

親クラスでメソッドを仮想として宣言し、派生クラスでそれをオーバーライドして機能を追加してみませんか?

于 2008-09-18T06:52:55.783 に答える
0

それがイベント ハンドラーであることを忘れて、子クラスで適切な通常のメソッド オーバーライドを行うだけです。

于 2008-09-18T07:09:28.757 に答える
0

以下は、いくつかの類似した形式で呼び出される基本メソッドを取得するために行ったことです。それぞれの形式には、一般的なものにいくつかの追加機能があります。

        protected override void OnLoad(EventArgs e)
    {
        try
        {
            this.SuspendLayout();
            base.OnLoad(e);

            foreach (Control ctrl in Controls)
            {
                Button btn = ctrl as Button;
                if (btn == null) continue;

                if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnAdd_Click);
                else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnEdit_Click);
                else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnDelete_Click);
                else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnPrint_Click);
                else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnExport_Click);
            }

正しい固定ボタン名を使用しない可能性は、継承されたハンドラーを手動で配線しない可能性と同じように見えます。

VS Designer でコードをまったくスキップするように this.DesignMode をテストする必要がある場合がありますが、チェックしなくても問題なく動作します。

于 2012-07-28T20:41:50.680 に答える