如何在 scrollviewer 控件中找到实际的滚动条高度
How to find the actual scrollbar height inside a scrollviewer control
我正在尝试为 canvas 进行智能滚动以扩大尺寸。我希望滚动条自动转到其范围的中心。所以我使用:
eagleViewer.ScrollToVerticalOffset(drawingSpace.Height/2);
eagleViewer.ScrollToHorizontalOffset(drawingSpace.Width/2);
这行得通,但是当滚动条滚动到超过半点时,它似乎是顶部对齐的。所以我想减去滚动条的高度或宽度,这样滚动条就会完美地居中于 canvas.
我在其他帖子中看到我可以做到这一点
SystemParameters.ScrollHeight
或
SystemParameters.ScrollWidth
但是它是如何工作的呢?我在 window 中有多个滚动查看器。我想要这个特定滚动查看器的滚动条的高度或宽度。
还有我不知道的其他方法吗?
谢谢
编辑:
添加 XAML 部分:
<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>
这应该可以完成工作:
scrollviewer.ScrollToVerticalOffset(scrollviewer.ScrollableHeight/2);
我在这里添加另一个答案,因为我想 post 更多代码。您提供了正确的关键字:"The canvas height change happens on the line before i run the scrolltoverticaloffset code"。通过这样做,我可以重现该问题。问题是 ScrollViewer 显然会在稍后评估 ScrollableHeight 属性。这意味着您需要延迟使用 ScrollableHeight。找到正确的点有点棘手。在我的以下测试应用程序中,我在内容的高度更改为滚动条居中后使用了第一个 ScrollChanged 事件。
<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);
}
}
}
}
我正在尝试为 canvas 进行智能滚动以扩大尺寸。我希望滚动条自动转到其范围的中心。所以我使用:
eagleViewer.ScrollToVerticalOffset(drawingSpace.Height/2);
eagleViewer.ScrollToHorizontalOffset(drawingSpace.Width/2);
这行得通,但是当滚动条滚动到超过半点时,它似乎是顶部对齐的。所以我想减去滚动条的高度或宽度,这样滚动条就会完美地居中于 canvas.
我在其他帖子中看到我可以做到这一点
SystemParameters.ScrollHeight
或
SystemParameters.ScrollWidth
但是它是如何工作的呢?我在 window 中有多个滚动查看器。我想要这个特定滚动查看器的滚动条的高度或宽度。
还有我不知道的其他方法吗?
谢谢
编辑:
添加 XAML 部分:
<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>
这应该可以完成工作:
scrollviewer.ScrollToVerticalOffset(scrollviewer.ScrollableHeight/2);
我在这里添加另一个答案,因为我想 post 更多代码。您提供了正确的关键字:"The canvas height change happens on the line before i run the scrolltoverticaloffset code"。通过这样做,我可以重现该问题。问题是 ScrollViewer 显然会在稍后评估 ScrollableHeight 属性。这意味着您需要延迟使用 ScrollableHeight。找到正确的点有点棘手。在我的以下测试应用程序中,我在内容的高度更改为滚动条居中后使用了第一个 ScrollChanged 事件。
<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);
}
}
}
}