Итак, после 2 дней попыток и ошибок я нашел решение для моей конкретной проблемы c. Прежде всего, есть две основные проблемы:
- Полосы прокрутки включены автоматически (они скрываются / отображаются во время выполнения в зависимости от width.height дочернего элемента внутри ScrollViewer ). Из-за этого изображение внутри изменяется, это трансформирующее преобразование.
- Положение полосы прокрутки (смещение) не сохраняется на той же позиции после действия увеличения / уменьшения (дочерний элемент становится больше или меньше).
Первая проблема была решена добавлением двух границ в ScrollViewer, которые будут занимать пространство, необходимое для полосы прокрутки, до тех пор, пока полосы прокрутки не видны.
<ScrollViewer x:Name="ScollViewerImage" Grid.Column="2" Grid.Row="0" Grid.RowSpan="3" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Column="1" Width="{x:Static SystemParameters.VerticalScrollBarWidth}">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding ComputedVerticalScrollBarVisibility, ElementName=ScollViewerImage}"
Value="Visible">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Grid.Row="1" Width="{x:Static SystemParameters.HorizontalScrollBarHeight}">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding ComputedHorizontalScrollBarVisibility, ElementName=ScollViewerImage}"
Value="Visible">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Controls:ZoomControl Grid.Column="0" Grid.Row="0" x:Name="RenderingImage" ViewModel="{Binding}" ClipToBounds="True"></Controls:ZoomControl>
</Grid>
</ScrollViewer>
Для второй проблемы, когда выполняется прокрутка, я сохраняю смещение. Я также сохраняю размер масштабирования (ScrollableHeight и Scorllable Width) и когда они меняются (увеличение / уменьшение было сделано). Я перемещаю полосу прокрутки в желаемое положение.
private void SetScrollbarOffset(ScrollViewer scrollViewer, double verticalChange, double horizontalChange)
{
// after each move of the scrollbar we save the current offsets
_currentVerticalOffset = scrollViewer.VerticalOffset;
_currentHorizonalOffset = scrollViewer.HorizontalOffset;
// we check if there was a zoom in/out perfomed
if (_scrollableHeight != scrollViewer.ScrollableHeight)
{
// we save the current zoom in/out scrollable height
_scrollableHeight = scrollViewer.ScrollableHeight;
// we move the scrollbar to the position needed to persist the mouse under the same point in the image
scrollViewer.ScrollToVerticalOffset(_currentVerticalOffset - verticalChange);
}
if (_scrollableWidth != scrollViewer.ScrollableWidth)
{
_scrollableWidth = scrollViewer.ScrollableWidth;
scrollViewer.ScrollToHorizontalOffset(_currentHorizonalOffset - horizontalChange);
}
}
Этот последний метод вызывается из SizeChangedEvent
public void SizeChange(ScrollChangedEventArgs e)
{
var scrollViewer = (e.OriginalSource as ScrollViewer);
SetScrollbarOffset(scrollViewer, e.VerticalChange, e.HorizontalOffset);
}