tags:

views:

21

answers:

1

Currently with a scrollviewer, clicking the scroll bar contained in it to pan the content around it will not focus the viewer (or anything for that matter). I wish to have it so when you scroll by dragging the scroll, or even clicking the scrollbar will focus the parent (scroll viewer).

I achieved this somewhat by attaching a ScrollChanged handler on the scrollviewer and calling sender.focus(). Unforutnally ScrollChanged is called on initialising the scrollviewer and so on loading the

I also tried attaching event setters with still no luck.

Ideally I would like it on some sort of style or something which allows me to apply it to all scrollviewers across the entire application.

Edit: Just for futher clarification, if I use this xaml and click on the scroll bar it will not turn the background blue (gotfocus event). When I click inside the scroll viewer or the button it will.

<Window x:Class="GotFocusProblem.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>
        <Grid Margin="20" x:Name="grid">
            <Grid.Background>
                <SolidColorBrush x:Name="backgrnd" Color="Transparent"/>
            </Grid.Background>
            <ScrollViewer Margin="10" Height="100" Background="#FFEEEEEE">
                <Button Content="Button" Name="button1" Height="300"  Width="75" />
            </ScrollViewer>
            <Grid.Triggers>
                <EventTrigger RoutedEvent="Grid.GotFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation
                            Storyboard.TargetName="backgrnd"
                            Storyboard.TargetProperty="Color"
                            To="Cyan"
                            BeginTime="0:0:0"
                            Duration="0:0:0" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Grid.Triggers>
        </Grid>
    </Grid>
</Window>
+1  A: 

I'm not 100% certain what you are looking for here but adding this code to your example will make the ScrollViewer receive focus when the ScrollBar is clicked, dragged etc. Some code behind is required for this solution though.

<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
    <EventSetter Event="PreviewMouseDown" Handler="scrollBar_PreviewMouseDown"/>            
</Style>

And in code behind

void scrollBar_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    c_scrollViewer.Focus();
}

UPDATE

You may know how to add this to a Resource Dictionary so you can access it for multiple ScrollViewers, otherwise here is how you can do it.

Add a Resource Dictionary to your project. I called mine ScrollBarStyles.xaml.
Add a code behind class for it, called ScrollBarStyles.xaml.cs.
Add an x:Class attribute in the xaml file, something like

x:Class="YourNameSpace.ScrollBarStyles"

ScrollBarStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="FocusScrollViewer.ScrollBarStyles">
    <Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
        <EventSetter Event="PreviewMouseDown" Handler="scrollBar_PreviewMouseDown"/>
    </Style>
</ResourceDictionary>

ScrollBarStyles.xaml.cs

public partial class ScrollBarStyles
{
    public T GetVisualParent<T>(object childObject) where T : Visual
    {
        DependencyObject child = childObject as DependencyObject;
        // iteratively traverse the visual tree
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }

    void scrollBar_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        ScrollBar scrollBar = sender as ScrollBar;
        ScrollViewer scrollViewer = GetVisualParent<ScrollViewer>(scrollBar);
        scrollViewer.Focus();
    }
}

Your Window

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="ScrollBarStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
Meleak
That is a really good answer. Thank you. While I had done a code behind for the specific scroll bar before to focus like you have I did not know how to do it in a style. In fact I did not realise that resource dictionaries could have code behinds. Very valuable information. Thanks!
Seravy