0

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

Ron
  • 3,975
  • 17
  • 80
  • 130
  • Can you please explain your problem more clearly... where is this `TabItem`? – Sheridan Nov 08 '13 at 11:24
  • I guess, you would have to live with that problem, as the event is bubbled up the tree to finally reach your handler. Another question, did you want to trigger function everytime the mouse enter/leave the ScrollBar or ScrollViewer? – Suresh Nov 08 '13 at 11:32
  • @sthotakura I believe that my edit answers your question, but I will answer here aswell - I want to trigger function when mouse enter/leave the ScrollViewer – Ron Nov 08 '13 at 11:42
  • Ahhhh... I think I know what you mean now. What are you trying to achieve with this handler? Maybe there's another way to do it? – Sheridan Nov 08 '13 at 12:23
  • Basicilly, the scrollbar is HIDDEN untill the user enter to the ScollViewer area and then the visibility of the scroll bar is changed to visible. – Ron Nov 08 '13 at 12:25
  • I just used *your* code example and I can clearly see scroll bars appear when I move my mouse over the `TabItem`s. – Sheridan Nov 08 '13 at 15:17
  • @Sheridan, I want the scroll bar to appear only when you `MouseOver` over the area defined by the red borders in the picture above... with the code above, it also appear when you `MouseOver` over the `TabItem` content area which is wrong – Ron Nov 08 '13 at 15:24

1 Answers1

2

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.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Same problem like my original problem. You did exactly what I wanted to do but using XAML instead of code... yet the problem remains the same – Ron Nov 08 '13 at 13:57
  • I don't know what you've done with this code, but the example code that I just ran in a new project worked just fine. Did you remove the un-needed `MouseEnter` event handler? – Sheridan Nov 08 '13 at 14:02
  • I have 2 different solutions. 1 to use mouse location to determine if I over what I want. 2. to use Mouse.DirectlyOver < or something like that to see what I over... isnt it better then recreating the tabcontrol? – Ron Nov 08 '13 at 16:08
  • my solutions didn't work. I want to try your solution, but I have no idea how to "bind" `RadioButton`s to different views... would appreciate your help – Ron Nov 08 '13 at 20:41