1

ボタンに ClickEvent- および PreviewMouseLeftButtonDown-Handler を追加することを検討してください

<Button x:Name="button"
    Click="Button_Click"
    PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown">
</Button>

ボタンをクリックすると、最初に PreviewMouseLeftButtonDown が発生し、次に Click-Event が発生します。

Preview...-Event で設定e.Handled = trueすると、Click-Event は処理されなくなります。

しかし、今度は MouseLeftButtonDownEvent について考えてみましょう。
まず、このイベントのルーティング戦略は直接的です。つまり、コントロールごとに再発生します。対照的に、Preview...-Event はトンネリングで、Click-Event はバブリングです。
次に、MouseLeftButtonDownEventHandler の追加は、次のコードの抜粋に示すように、既に処理されたイベントに対しても呼び出されるようにハンドラーを登録する場合にのみ成功します。

button.AddHandler(MouseLeftButtonDownEvent,
                  new MouseButtonEventHandler(Button_MouseLeftButtonDown),
                  true);

ボタンを持つテスト アプリケーションを作成し、各イベントのハンドラーを追加しました。イベント ハンドラーが呼び出されると、いくつかの情報がテキスト ブロックに書き込まれます。

  • ボタンをクリックすると、3 つのイベント ハンドラーがすべて呼び出されます。
  • e.Handled = truePreview...-EventHandlerに追加すると、このイベント ハンドラーのみが呼び出されます。trueに設定しましたが、Mouse...-EventHandler も発生しませんUIElement.AddHandler handledEventsToo
  • Mouse...-EventHandlerに追加e.Handled = trueすると、3 つのイベント ハンドラーがすべて呼び出されます。

それは私には意味がありません。Mouse...-EventHandlers は Click-EventHandlers には影響しませんが、Preview...-EventHandlers は Mouse...- と Click-EventHandlers の両方に影響します。
そして、イベントを処理するための「強制」でさえ、Mouse...-EventHandler では失敗しました。

実際、異なるタイプのイベント ハンドラーが互いに影響を与える可能性があるとは考えもしませんでした。私が理解したのは、Preview...-Event と Click-Event がある場合、これらは独立しているということです。

それで、私は何が欠けていますか?


非常に単純なサンプルコードは次のとおりです。

XAML:

<DockPanel>
    <Border x:Name="border" DockPanel.Dock="Top" Height="50"
            BorderBrush="Gray" BorderThickness="1">
        <StackPanel x:Name="stackpanel" Background="LightGray"
                    Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="button" Width="Auto" 
                    PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown">
                Click Me
            </Button>
        </StackPanel>
    </Border>
    <Border DockPanel.Dock="Bottom" BorderBrush="Gray" BorderThickness="1">
        <ScrollViewer>
            <TextBlock x:Name="textBlock" TextWrapping="Wrap"/>
        </ScrollViewer>
    </Border>
</DockPanel>

コード ビハインド:

public MainWindow()
{
    InitializeComponent();

    button.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(Button_MouseLeftButtonDown), true);
    button.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click), true);
    stackpanel.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click), true /*false*/ );
}

private void Output(object sender, RoutedEventArgs e)
{
    textBlock.Text += "RoutedEvent: " + e.RoutedEvent + "\n";
    textBlock.Text += "Sender: " + sender + "\n";
    textBlock.Text += "Source: " + e.Source + "\n";
    textBlock.Text += "OriginalSource: " + e.OriginalSource + "\n" + "\n";
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    // e.Handled = true;
    Output(sender, e);
}

private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    // e.Handled = true;
    Output(sender, e);
}

private void Button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Output(sender, e);
}
4

1 に答える 1

2

異なるタイプのイベント ハンドラーが互いに影響を与える可能性があるとは考えもしませんでした

これは非常にまれであるため、おおむね正解ですが、MSDN のプレビュー イベントページで回答を見つけることができます。リンクされたページから:

たとえば、Windows Presentation Foundation (WPF) ボタンは、ボタンまたはその複合要素によって発生する MouseLeftButtonDown および MouseLeftButtonDown バブリング イベントを抑制し、マウスをキャプチャして、ボタン自体によって常に発生する Click イベントを発生させます。イベントとそのデータは引き続きルートに沿って続きますが、Button はイベント データを Handled としてマークするため、handledEventsToo ケースで動作する必要があることを明確に示したイベントのハンドラーのみが呼び出されます。

さらに、あなたはこう言いました。

e.Handled = true を Mouse...-EventHandler に追加すると、3 つのイベント ハンドラーがすべて呼び出されます。

e.Handledバブリング イベント ハンドラーでの設定は何も行わないため、これは予想されることです...イベントがハンドラー コードを離れた後、その値を読み取るものは何もありません。e.Handled主にトンネリングイベントハンドラーで使用され、イベントがそれ以上ルーティングされないようにします。繰り返しますが、リンクされたページから:

特に入力イベントの場合、プレビュー イベントは、イベント データ インスタンスを同等のバブリング イベントと共有します。Preview イベント クラス ハンドラーを使用して入力イベントを処理済みとしてマークすると、バブリング入力イベント クラス ハンドラーは呼び出されません。または、Preview イベント インスタンス ハンドラーを使用してイベントを処理済みとしてマークすると、通常、バブル イベントのハンドラーは呼び出されません。

于 2014-08-06T09:57:52.307 に答える