【问题标题】:WPF disable MouseEnter trigger on childrenWPF 在子级上禁用 MouseEnter 触发器
【发布时间】:2013-11-08 11:03:14
【问题描述】:

我在ScrollViewer 里面有TabPanel

<ScrollViewer x:Name="ScrollViewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden">
    <TabPanel x:Name="HeaderPanel" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1" Background="Red"/>
</ScrollViewer>

我想在每次鼠标进入/离开 ScrollViewer 时触发函数。

如果我这样使用它:

ScrollViewer sv = GetTemplateChild("ScrollViewer") as ScrollViewer;
sv.MouseEnter += sv_MouseEnter;

即使我进入TabItem's 内容区域,该功能也会被触发。
我该如何解决?

编辑:
我将解释下面的图像。 当用户进入由红色边框定义的区域(即ScrollViewer)时,我想触发MouseEnter

但实际上,当我使用上面的代码时,当我输入TabControl 时,它会触发MouseEnter

编辑 2:
根据 Sheridan 的回答,这是我的 xaml。

我的 MainWindow.xaml:

<Window x:Class="WpfApplication26.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl Style="{DynamicResource TabControlStyle1}" >
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

我的 App.xaml:

<Application x:Class="WpfApplication26.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
        <Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="Padding" Value="4,4,4,4"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
            <Setter Property="Background" Value="#F9F9F9"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition x:Name="ColumnDefinition0"/>
                                <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                                <RowDefinition x:Name="RowDefinition1" Height="*"/>
                            </Grid.RowDefinitions>
                            <ScrollViewer>
                                <TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
                                <ScrollViewer.Style>
                                    <Style>
                                        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
                                        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
                                        <Style.Triggers>
                                            <Trigger Property="UIElement.IsMouseOver" Value="True">
                                                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Visible" />
                                            </Trigger>
                                        </Style.Triggers>
                                    </Style>
                                </ScrollViewer.Style>
                            </ScrollViewer>

                            <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                                <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="TabStripPlacement" Value="Bottom">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                                <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
                            </Trigger>
                            <Trigger Property="TabStripPlacement" Value="Left">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                                <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                                <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
                            </Trigger>
                            <Trigger Property="TabStripPlacement" Value="Right">
                                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                                <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                                <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Application.Resources>
</Application>

虽然他说可以,但没有按应有的方式工作(在第一次编辑中解释)......

【问题讨论】:

  • 您能否更清楚地解释您的问题...这是哪里的TabItem
  • 我猜,你将不得不忍受这个问题,因为事件在树上冒泡最终到达你的处理程序。还有一个问题,你想每次鼠标进入/离开 ScrollBar 或 ScrollViewer 时触发函数吗?
  • @sthotakura 我相信我的编辑回答了你的问题,但我也会在这里回答 - 我想在鼠标进入/离开 ScrollViewer 时触发功能
  • 啊……我想我现在明白你的意思了。你想用这个处理程序实现什么?也许还有其他方法可以做到这一点?
  • 基本上,滚动条是隐藏的,直到用户进入 ScollViewer 区域,然后滚动条的可见性才变为可见。

标签: wpf custom-controls scrollviewer mouseenter event-bubbling


【解决方案1】:

好的...这就是为什么您应该始终向我们展示您的总体目标是什么。如果我没有这样问,那么您可能无法得到答案,因为您最初找错了地方。对了,讲完,继续回答。

事实上,它既好又简单......我们不需要处理任何事件,我们可以在ScrollViewer.Style 中使用Trigger。只需将此添加到您的 ScrollViewer (确保从 ScrollViewer 定义中删除您的 ScrollBar 属性):

<ScrollViewer x:Name="ScrollViewer">
    ...
    <ScrollViewer.Style>
        <Style>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" 
                Value="Disabled" />
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" 
                Value="Disabled" />
            <Style.Triggers>
                <Trigger Property="UIElement.IsMouseOver" Value="True">
                    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" 
                        Value="Visible" />
                    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" 
                        Value="Visible" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ScrollViewer.Style>
</ScrollViewer>

更新>>>

好的,我现在终于完全理解你的问题了……抱歉这么慢。但是,您在这里遇到了一个真正的问题,因为这不是错误,而是设计的行为。这是因为TabItem 控件ScrollViewer 控件内,因此将鼠标移到它们上与将它们移到ScrollViewer 上是一样的。

如果我试图实现您的要求,我将完全放弃TabControl,而只使用将视图加载到下部区域的RadioButton 控件。如果您愿意,您甚至可以将您的 RadioButtons 设置为看起来像标签。


更新 2 >>>

这是一个很长的故事,有几个部分。我没有时间在这里输入整个内容,但我会简要地告诉你。首先,您必须为RadioButtons 创建一个新的ControlTemplate,然后您可以将它们放入StackPanel 并将其Orientation 属性设置为True,然后将其放入您的ScrollViewer

接下来,您需要为每个“选项卡”或视图定义一个 enum,并为每个“选项卡”或视图定义一个值,以及一个 EnumToBoolConverter...我在 How to bind RadioButtons to an enum? 帖子中为您找到了一个很好的示例。

接下来的工作是创建“标签项内容”区域。为此,您需要ContentControl 来显示每个视图或选项卡项内容。这个想法是你有一个抽象的BaseViewModel 类,它实现了INotifyPropertyChanged 接口和一个为你想要显示的每个选项卡扩展这个基类的类。每个类都将提供相关视图或选项卡所需的所有数据属性和功能。

因为它们都扩展了基类,所以您可以拥有该类型的属性,您可以将其设置为每个扩展视图模型。这就是ContentControl 发挥作用的地方,因为它绑定到BaseViewModel 属性。

最后一部分是为每个简单显示相关视图的视图模型类定义一个DataTemplate。 Then when the various RadioButtons are selected, you can just set the BaseViewModel property to the relevant view model which will result in the paired view being displayed.您可以在我对WPF MVVM navigate views 帖子的回答中看到更完整的代码示例说明。

【讨论】:

  • 和我原来的问题一样的问题。你做了我想做的事,但使用 XAML 而不是代码......但问题仍然存在
  • 我不知道你对这段代码做了什么,但是我刚刚在一个新项目中运行的示例代码运行良好。您是否删除了不需要的 MouseEnter 事件处理程序?
  • 我有 2 种不同的解决方案。 1 使用鼠标位置来确定我是否超过了我想要的。 2. 使用 Mouse.DirectlyOver
  • 我的解决方案不起作用。我想尝试您的解决方案,但我不知道如何“绑定”RadioButtons 到不同的视图...不胜感激您的帮助
猜你喜欢
  • 2021-12-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-23
相关资源
最近更新 更多