Search code examples
c#wpfvisibilityscrollviewertextblock

How can I see whether a scrollviewer child element is visible, and make it visible if it isn't?


In a scrollviewer I have a textblock with 1000 inlines e.g.

XAML

<Grid>
    <ScrollViewer>
        <TextBlock Name="textBlock1" TextWrapping="Wrap" />
    </ScrollViewer>        
</Grid>

C#

public MainWindow()
    {
        InitializeComponent();

        for (int i = 0; i < 1000; i++)
        {
            textBlock1.Inlines.Add(new Run("Inline number " + i.ToString() + ". "));
        }
    }

How do I see if a particular inline element (e.g. number 850) is visible and, if it isn't, get the scrollviewer to scroll so that it is.

I'm fairly new to C# and wpf.

Thanks for your help.


Solution

  • Since the Run objects aren't Visuals you cannot use ScrollIntoView like you might be able to for some objects. I was able to accomplish it by locating the top offset of the desired Run and instructing the scrollviewer to scroll to that offset.

        <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
    
        <Button Grid.Row="0" x:Name="findButton" Click="findButton_Click_1">Find It</Button>
        <ScrollViewer x:Name="scrollViewer1" Grid.Row="1">
            <TextBlock Name="textBlock1" TextWrapping="Wrap" />
        </ScrollViewer>
    </Grid>
    

    Here is the code-behind. It's hard-coded to find Run # 850...

            Run target;
    
        public MainWindow()
        {
            InitializeComponent();
    
            for (int i = 0; i < 1000; i++)
            {
                var run = new Run("Inline number " + i.ToString() + ". ");
                if (i==850)
                    target = run;
                textBlock1.Inlines.Add(run);
            }
        }
    
        public void findButton_Click_1(object sender, RoutedEventArgs e)
        {
            var contentStart = target.ContentStart;
            var rect = contentStart.GetCharacterRect(LogicalDirection.Forward);
            scrollViewer1.ScrollToVerticalOffset(rect.Top);
        }