WPF EventHandler fired on the wrong Element

笑着哭i 提交于 2019-12-02 01:44:35

Gee, you've uncovered a very strange behavior indeed. It appears that the mouse handling for all the elements that are part of a TextBoxBase control template can be revectored to the text content element and then tunnel/bubble from there. As a result, including a label in a rich text box control template means it will participate in mouse events on the rich text as though it were part of the rich text itself.

To work around this problem, you can use a ContentControl that includes the associated elements and then forwards its Content property to a "normal" TextBoxBase derived element. Here is a simplified XAML example. The first section reproduces the strange behavior in a simpler example and the second section shows how to use a ContentControl to work around the problem.

<Grid>
    <StackPanel>
        <TextBox Text="Some text">
            <TextBox.Template>
                <ControlTemplate TargetType="TextBox">
                    <StackPanel>
                        <Rectangle Fill="Green" Width="200" Height="50"/>
                        <Border x:Name="RedBorder" PreviewMouseDown="Border_PreviewMouseDown" Background="Red">
                            <AdornerDecorator x:Name="PART_ContentHost" />
                        </Border>
                    </StackPanel>
                </ControlTemplate>
            </TextBox.Template>
        </TextBox>
        <ContentControl Content="Some text">
            <ContentControl.Template>
                <ControlTemplate TargetType="ContentControl">
                    <StackPanel>
                        <Rectangle Fill="Green" Width="200" Height="50"/>
                        <Border x:Name="RedBorder" PreviewMouseDown="Border_PreviewMouseDown" Background="Red">
                            <TextBlock Text="{TemplateBinding Content}"/>
                        </Border>
                    </StackPanel>
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>
    </StackPanel>
</Grid>

You're missing bubbling events here. http://msdn.microsoft.com/en-us/library/ms742806.aspx#routing_strategies

You can check RoutedEventArgs.OriginalSource to determine which border was clicked.

UPDATE: Ok, it looks like I missed, but not completely. I've played for some time with your sample, it looks like RichTextBox (or probably TextBoxBase) does something with PART_ContentHost which forces tunnelling events to go towards this part. Your sample behaves well out of RichTextBox so I assume it does something with own template. Though I do not how to investigate it further without going into .Net sources.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!