Reputation: 115
I'm trying to make smart scrolling for a canvas that expands in size. I want the scrollbars to automatically go to the center of their range. So I use:
eagleViewer.ScrollToVerticalOffset(drawingSpace.Height/2);
eagleViewer.ScrollToHorizontalOffset(drawingSpace.Width/2);
Which works but when the scrollbars scroll they go beyond the half point, it seems it's top aligned. So I wanted to subtract the scrollbar Height or Width so the scrollbars would be perfectly centered at the canvas.
I read in other posts that I can do this is at
SystemParameters.ScrollHeight
or
SystemParameters.ScrollWidth
But how does that work? I have multiple scrollviewers in the window. I want the height or width of the scrollbars of this specific scrollviewer.
Any other way I'm not aware off?
Thanks
Edit:
Adding XAML section:
<ScrollViewer Name="eagleViewer" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Height="Auto" Width="Auto">
<Grid Name="eagleGrid" Background="LightGray">
<Canvas Name="drawingSpace" Background="WhiteSmoke" Width="100" Height="100">
<Canvas.LayoutTransform>
<ScaleTransform CenterX="0" CenterY="0" ScaleX="{Binding ElementName=zoomEagleSlider,Path=Value}" ScaleY="{Binding ElementName=zoomEagleSlider,Path=Value}"/>
</Canvas.LayoutTransform>
</Canvas>
</Grid>
</ScrollViewer>
Upvotes: 2
Views: 3166
Reputation: 2519
I add another answer here because I like to post some more code. You gave the right keyword: "The canvas height change happens on the line before i run the scrolltoverticaloffset code". By doing this I can reproduce the problem. The problem is the ScrollViewer obviously evaluates the ScrollableHeight property at a later point. Which means you need to delay using ScrollableHeight. It is a bit tricky to find the right point. In my following test application I use the first ScrollChanged event after the content's height was changed to center the scrollbar.
<Window x:Class="ScrollViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<ScrollViewer Name="SV"
Margin="71,62,10,10"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Border x:Name="SVContent" Background="#FFFFA6A6"
BorderBrush="#FF005DFF"
Width="200"
Height="200"
BorderThickness="1" />
</ScrollViewer>
<Button Width="75"
Margin="28,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Button" />
</Grid>
</Window>
cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace ScrollViewer
{
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
SV.ScrollChanged += ScrollChangedEventHandler;
}
bool firstScrollAfterContenChanged;
private void Button_Click (object sender, RoutedEventArgs e)
{
firstScrollAfterContenChanged = true;
SVContent.Height = 1000;
}
public void ScrollChangedEventHandler(Object sender, ScrollChangedEventArgs e)
{
if (firstScrollAfterContenChanged)
{
firstScrollAfterContenChanged = false;
SV.ScrollToVerticalOffset (SV.ScrollableHeight / 2);
}
}
}
}
Upvotes: 1
Reputation: 2519
This should do the job:
scrollviewer.ScrollToVerticalOffset(scrollviewer.ScrollableHeight/2);
Upvotes: 0