11

メイン フォームがユーザー コントロールのサブコントロールで発生するイベントをインターセプトできる方法はありますか?

アプリケーションのメイン フォームにカスタム ユーザー コントロールが埋め込まれています。コントロールには、データを操作するさまざまなサブコントロールが含まれており、それ自体がメイン フォーム上の他のコントロールによって表示されます。私が望むのは、ユーザーがサブコントロールを変更したときに何らかの方法でメイン フォームに通知できれば、データと対応する表示を別の場所で更新できるということです。

今、私は浮気をしています。サブコントロールのフォーカス離脱イベントに接続されたデリゲートがあります。このデリゲートは、他の場所では使用していないユーザー コントロールのプロパティを変更します (この原因では、CausesValidation)。次に、ユーザー コントロールの CausesValidation プロパティが変更されたときのためにメイン フォームにデリゲートを定義し、アプリにデータの更新と表示を指示します。

ユーザーが他の操作を実行できるようにする前に、ユーザー コントロールのフィールドを検証する必要があるため、フォーカスがユーザー コントロールから離れたときにデリゲートを設定しているため、問題が発生します。ただし、ユーザーがサブコントロールを切り替えているだけの場合は、編集が完了していない可能性があるため、検証したくありません。

基本的に、ユーザーがサブコントロールを切り替えたり、ユーザーコントロールを離れたりしたときにデータを更新したいのですが、検証はしません。ユーザーがコントロールを離れたら、更新して検証したいと思います。現在、ユーザー コントロールを離れると、検証が 2 回発生します。

4

5 に答える 5

15

UserControlベスト プラクティスは、イベントを親フォームにバブリングする でイベントを公開することです。私は先に進み、あなたのために例をまとめました. 以下は、この例が提供する内容の説明です。

  • UserControl1
  • UserControlで_TextBox1
  • UserControl呼び出された上で公開イベントを登録するControlChanged
  • register内で、 TextChangedEventUserControlのイベント ハンドラーTextBox1
  • TextChangeEventハンドラー関数内でControlChanged、親フォームにバブルするイベントを呼び出します
  • Form1
  • のインスタンスをUserControl1デザイナーにドロップする
  • UserControl1forMouseLeaveと forにイベント ハンドラーを登録するControlChanged

ControlChangedで定義したイベントがUserControl、親 Windows フォームの Visual Studio の UX を介して利用できることを示すスクリーンショットを次に示します。

ユーザー コントロールのイベント ハンドラ

于 2008-10-02T16:14:45.080 に答える
2

キャプチャする必要のあるイベントをユーザーコントロール内に接続し、ユーザーコントロール自体のいくつかのカスタムイベントプロパティを介して公開する必要があります。簡単な例は、ボタンクリックイベントをラップすることです。

// CustomControl.cs
// Assumes a Button 'myButton' has been added through the designer

// we need a delegate definition to type our event
public delegate void ButtonClickHandler(object sender, EventArgs e);

// declare the public event that other classes can subscribe to
public event ButtonClickHandler ButtonClickEvent;

// wire up the internal button click event to trigger our custom event
this.myButton.Click += new System.EventHandler(this.myButton_Click);
public void myButton_Click(object sender, EventArgs e)
{
  if (ButtonClickEvent != null)
  {
    ButtonClickEvent(sender, e);
  }
}

次に、そのコントロールを使用するフォームで、他の場合と同じようにイベントを接続します。

// CustomForm.cs
// Assumes a CustomControl 'myCustomControl' has been added through the desinger
this.myCustomControl.ButtonClickEvent += new System.EventHandler(this.myCustomControl_ButtonClickEvent);
myCustomControl_ButtonClickEvent(object sender, EventArgs e)
{
  // do something with the newly bubbled event
}
于 2010-03-29T18:25:23.323 に答える
2

この種の最適なモデルは、ユーザー コントロールでカスタム イベントを作成し、適切なタイミングで発生させることです。

あなたのシナリオはかなり複雑ですが、前代未聞ではありません。(私は実際、私の現在のプロジェクトの 1 つで非常によく似たモードにいます。) 私がアプローチする方法は、ユーザー コントロールが独自の検証を担当するということです。私はCausesValidationを使用しません。代わりに、適切なユーザー コントロール ポイントで、ValidateChildren() をオーバーライドして検証を実行します。(これは通常、ユーザーがユーザー コントロールで [保存] または [次へ] をクリックしたときに発生します。)

ユーザー コントロール UI に慣れていないため、100% 適切なアプローチではない可能性があります。ただし、カスタム イベントを発生させる場合 (おそらく、検証を実行するかどうかを指定するカスタム EventArgs を使用して)、目的の場所に到達できるはずです。

于 2008-10-02T15:53:09.500 に答える
1

WinForm でイベント バブリングをシミュレートする方法をまだ疑問に思っている場合は、メソッドApplication.AddMessageFilterを参照することをお勧めします。

このメソッドを使用すると、現在のスレッドのメッセージ キューにポストされるすべてのメッセージを監視する独自のフィルターをインストールできます。

送信された (投稿されていない) メッセージは、このフィルターでは処理できないことに注意してください。当然のことながら、最も興味深いイベント (クリック イベントなど) は投稿され、送信されないため、このフィルターで監視できます。

于 2015-02-04T20:03:52.053 に答える
0

その中でチャイムを鳴らしたいと思います。説明したように、実際にはあなたが赤いニシンを追いかけているように聞こえます。WinFormsでのイベントのバブリングの欠如が問題を引き起こしているように見えますが、実際には、アーキテクチャが貧弱であるために、必要のないときにイベントのバブリングが必要になります。

コントロールが共通のデータモデルで機能するようにデザインをリファクタリング/再構築できる場合(MVC / MVPは明らかな選択です)、モデルにPropertyChangedイベントなどの一般的なWinFormsパターンを適用するだけで、メインフォームやその他のコントロールに通知できます。そのデータを消費して自分自身を更新します。

要するに、他の答えは、彼らが尋ねられたように質問に答えるという点で合理的です。しかし、コード品質の観点から、より良い答えはUIからデータを分離することだと思います。

于 2010-03-29T18:34:59.840 に答える