web-dev-qa-db-ja.com

コントロールは、そのコントロールの外でのマウスクリックをどのように処理できますか?

カスタムコントロールを作成していて、ユーザーがコントロールをクリックすると、コントロールが編集状態から通常の状態に切り替わります。私はLostFocusイベントを処理しています。これは、ユーザーがタブを離したとき、またはフォーカス可能な別のコントロールをクリックしたときに役立ちます。しかし、フォーカス可能なものをクリックしないと、編集状態から切り替わりません。だから私は2つの解決策を考えています:

  • 編集状態になると、ツリーを最上位の要素に移動し、MouseDownEventのハンドラーを追加します(「処理された」イベントを処理します)。ハンドラーでは、コントロールの編集状態を解除し、ハンドラーを一番上の要素から削除します。これは少しハックのように見えますが、おそらくうまくいくでしょう。

コード例:

private void RegisterTopMostParentMouseClickEvent()
{
   _topMostParent = this.FindLastVisualAncestor<FrameworkElement>();
   if ( _topMostParent == null )
      return;
   _topMostParent.AddHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ), true );
}

private void UnRegisterTopMostParentMouseClickEvent()
{
   if ( _topMostParent == null )
      return;
   _topMostParent.RemoveHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ) );
   _topMostParent = null;
}
  • 使用する Mouse.PreviewMouseDownOutsideCapturedElementとハンドラーをコントロールに追加します。ハンドラーでは、コントロールの編集状態を解除します。しかし、イベントが発生するようには思えません。 Mouse.PreviewMouseDownOutsideCapturedElementはいつキックオフされますか?

コード例:

AddHandler( Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler( EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent ), true );
26
chrislarson

マウスをキャプチャします。オブジェクトがマウスをキャプチャすると、マウスポインターが別のオブジェクト上にある場合でも、マウスキャプチャーを持つオブジェクトがイベントを実行するかのように、すべてのマウス関連イベントが処理されます。

13
Dmytro Laptin

マウスフォーカスについて提供された答えを明確にするためだけに-それは便利でしたが、実際に機能するものを得るために、さらに掘り下げたり、いじったりしなければなりませんでした。

私はコンボボックスのようなものを実装しようとしていて、同様の動作が必要でした-他の何かをクリックしたときにドロップダウンが消えるようにし、コントロールが他の何かについての知識を持たないようにしました。

ドロップダウンボタンの次のイベントがありました。

    private void ClickButton(object sender, RoutedEventArgs routedEventArgs)
    {
        //do stuff (eg activate drop down)
        Mouse.Capture(this, CaptureMode.SubTree);
        AddHandler();
    }

CaptureMode.SubTreeは、コントロールの外部にあるイベントのみを取得し、コントロール内のマウスアクティビティは通常どおりに通過することを意味します。 UIElementのCaptureMouseでこのEnumを提供するオプションはありません。これは、子コントロールまたはコントロール内の他のハンドラーへの呼び出しのHandleClickOutsideOfControl INSTEADへの呼び出しを取得することを意味します。これは、彼らが使用しているイベントにサブスクライブしない場合でも当てはまります-完全なマウスキャプチャは少し多すぎます!

    private void AddHandler()
    {
        AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true);
    }

また、適切な時点でハンドラーを+削除する必要がありますが、ここでは、わかりやすくするために省略しています。

最後に、ハンドラーでキャプチャを再度解放する必要があります。

    private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
    {
        //do stuff (eg close drop down)
        ReleaseMouseCapture();
    }
36
JonnyRaa

私は通常、親ウィンドウを取得して、すでに処理されていてもプレビューハンドラを追加します。場合によっては、MouseCaptureでは不十分な場合に、このテクニックが便利です。

Window.GetWindow(this).AddHandler
(
    UIElement.MouseDownEvent,
    (MouseButtonEventHandler)TextBox_PreviewMouseDown,
    true
);
1
Mauro Sampietro

私はこれに別の方法でアプローチします-コントロールを含むフォームに、ユーザーがフォームの別の部分をクリックしたときにコントロールからフォーカスを削除させます。

コントロールがあること実際にフォーカスが緩んでいることは、特定の状況でコントロールが「シミュレート」フォーカスを失うことを試みるよりもはるかにクリーンです。コントロールが本当にフォーカスを失っていない限り、キーボード入力のようなものを受け入れます。

0
Justin