Frage

I have TabPanel inside ScrollViewer.

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

I want to trigger function everytime the mouse enter/leave the ScrollViewer.

If I use it like that:

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

the function is being tirggered even if I enter the TabItem's content area.
How can I solve it?

EDIT:
I will explain about the image below. I want to trigger MouseEnter when ever the user enter the area defined by the red border (which is the ScrollViewer).

But in reality, when I use the code above, when ever I enter the TabControl, it tirggers the MouseEnter.

enter image description here

EDIT 2:
based on Sheridan's answer, here's my xaml.

my 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>

my 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>

not working as It should (explained in the first edit) even though he says it does...

War es hilfreich?

Lösung

Ok... this is why you should always show us what your overall goal is. Had I not asked that, then you might not have got an answer because you were initially looking in the wrong place. Right, lecture over, on to the answer.

As it is, it's nice and simple... we don't need to handle any events, we can just use a Trigger in the ScrollViewer.Style. Just add this to your ScrollViewer (making sure that you remove your ScrollBar properties from the ScrollViewer definition):

<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>

UPDATE >>>

Ok, I finally fully understand your question now... sorry for being so slow. However, you have a real problem here because this is not an error, it is the designed behaviour. This is because the TabItem controls are inside the ScrollViewer control, so moving the mouse over them is the same as moving them over the ScrollViewer.

If I were trying to implement your requirements, I would abandon the TabControl altogether and just use RadioButton controls that load views into the lower area instead. You could even style your RadioButtons to look like tabs if you wanted.


UPDATE 2 >>>

Well that's a long story with several parts. I don't have time to type the whole thing out here, but I'll talk you through it briefly. First you'll have to create a new ControlTemplate for the RadioButtons and you can put them in a StackPanel with its Orientation property set to True, then put that in your ScrollViewer.

Next, you'll need to define an enum with one value for each 'tab' or view and an EnumToBoolConverter... I found a good example for you in the How to bind RadioButtons to an enum? post.

The next job is to create the 'tab item content' area. For this you'll need a ContentControl to display each view, or tab item content. The idea is that you have an abstract BaseViewModel class that implements the INotifyPropertyChanged interface and a class that extends this base class for each tab that you want to display. Each class will provide all of the data properties and functionality that the related view, or tab requires.

Because they all extend the base class, you can have a property of that type that you can set to each of the extended view models. This is where the ContentControl comes into play, as it binds to the BaseViewModel property.

The final part is to define a DataTemplate for each view model class that simply displays the related view. 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. You can see a fuller explanation with code examples in my answer to the WPF MVVM navigate views post.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top