WPF ScrollViewer 和平移
WPF ScrollViewer and Panning
我有一个 Window
和一个 ScrollViewer
,在 ScrollViewer
里面有一个 Rectangle
。现在我添加了代码来拖动 Rectangle
,效果很好。但是当 Rectangle
移出视图时,我不知道如何显示 Scrollbars
。我以为这会自动发生,但事实并非如此?
这是我的 XAML:
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<ScrollViewer Name="_scrollViewer" CanContentScroll="True"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue"/>
</ScrollViewer>
</Window>
后面的代码:
public partial class MainWindow : Window
{
private Point _origin;
private Point _start;
private ScaleTransform _scaleTransform = new ScaleTransform();
private TranslateTransform _translateTransform = new TranslateTransform();
public MainWindow()
{
InitializeComponent();
var group = new TransformGroup();
group.Children.Add(_scaleTransform);
group.Children.Add(_translateTransform);
_myRect.RenderTransform = group;
// Hook up events
_myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
_myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
_myRect.MouseMove += _myRect_MouseMove;
}
private void _myRect_MouseMove(object sender, MouseEventArgs e)
{
if (_myRect.IsMouseCaptured)
{
Vector v = _start - e.GetPosition(this);
_translateTransform.X = _origin.X - v.X;
_translateTransform.Y = _origin.Y - v.Y;
}
}
private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_myRect.ReleaseMouseCapture();
this.Cursor = Cursors.Arrow;
}
private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_start = e.GetPosition(this);
_origin = new Point(_translateTransform.X, _translateTransform.Y);
Cursor = Cursors.Hand;
_myRect.CaptureMouse();
}
}
[更新]:
因此,根据我得到的输入,我将 XAML 和后面的代码更改为以下内容 - 但仍然没有滚动条?
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<ScrollViewer Name="_scrollViewer" CanContentScroll="True"
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Canvas Name="_myCanvas">
<Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue" Canvas.Left="305" Canvas.Top="129"/>
</Canvas>
</ScrollViewer>
</Window>
隐藏代码:
public partial class MainWindow : Window
{
private Point _start;
public MainWindow()
{
InitializeComponent();
// Hook up events
_myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
_myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
_myRect.MouseMove += _myRect_MouseMove;
}
private void _myRect_MouseMove(object sender, MouseEventArgs e)
{
if (_myRect.IsMouseCaptured)
{
var canvasRelativePosition = e.GetPosition(_myCanvas);
Debug.WriteLine($"New Position: {canvasRelativePosition}");
Canvas.SetTop(_myRect, canvasRelativePosition.Y - _start.Y);
Canvas.SetLeft(_myRect, canvasRelativePosition.X - _start.X);
}
}
private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_myRect.ReleaseMouseCapture();
this.Cursor = Cursors.Arrow;
}
private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_start = e.GetPosition(_myRect);
Debug.WriteLine($"Start Position: {_start}");
Cursor = Cursors.Hand;
_myRect.CaptureMouse();
}
}
如果您希望变换影响布局,则必须使用 LayoutTransofrm
。 RenderTransform
只改变外观。
Any transformations associated with an elements LayoutTransform
property will have an impact on the subsequent Measure and Arrange
steps. Whereas a RenderTransform will not have any impact on the
layout process and will only effect rendering.
阅读更多here。
但是,LayoutTransform
忽略了 TranslateTransform
LayoutTransform ignores TranslateTransform operations. This is because
the layout system behavior for child elements of a FrameworkElement
auto-corrects any offsets to the position of a scaled or rotated
element into the layout and coordinate system of the parent element.
阅读更多here
也就是说,要实现元素的移动,不能使用Transforms
。您可以尝试手动更改元素的位置(Margin
、Canvas.Left/Right
或其他想法)。
我有一个 Window
和一个 ScrollViewer
,在 ScrollViewer
里面有一个 Rectangle
。现在我添加了代码来拖动 Rectangle
,效果很好。但是当 Rectangle
移出视图时,我不知道如何显示 Scrollbars
。我以为这会自动发生,但事实并非如此?
这是我的 XAML:
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<ScrollViewer Name="_scrollViewer" CanContentScroll="True"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue"/>
</ScrollViewer>
</Window>
后面的代码:
public partial class MainWindow : Window
{
private Point _origin;
private Point _start;
private ScaleTransform _scaleTransform = new ScaleTransform();
private TranslateTransform _translateTransform = new TranslateTransform();
public MainWindow()
{
InitializeComponent();
var group = new TransformGroup();
group.Children.Add(_scaleTransform);
group.Children.Add(_translateTransform);
_myRect.RenderTransform = group;
// Hook up events
_myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
_myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
_myRect.MouseMove += _myRect_MouseMove;
}
private void _myRect_MouseMove(object sender, MouseEventArgs e)
{
if (_myRect.IsMouseCaptured)
{
Vector v = _start - e.GetPosition(this);
_translateTransform.X = _origin.X - v.X;
_translateTransform.Y = _origin.Y - v.Y;
}
}
private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_myRect.ReleaseMouseCapture();
this.Cursor = Cursors.Arrow;
}
private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_start = e.GetPosition(this);
_origin = new Point(_translateTransform.X, _translateTransform.Y);
Cursor = Cursors.Hand;
_myRect.CaptureMouse();
}
}
[更新]: 因此,根据我得到的输入,我将 XAML 和后面的代码更改为以下内容 - 但仍然没有滚动条?
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<ScrollViewer Name="_scrollViewer" CanContentScroll="True"
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Canvas Name="_myCanvas">
<Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue" Canvas.Left="305" Canvas.Top="129"/>
</Canvas>
</ScrollViewer>
</Window>
隐藏代码:
public partial class MainWindow : Window
{
private Point _start;
public MainWindow()
{
InitializeComponent();
// Hook up events
_myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
_myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
_myRect.MouseMove += _myRect_MouseMove;
}
private void _myRect_MouseMove(object sender, MouseEventArgs e)
{
if (_myRect.IsMouseCaptured)
{
var canvasRelativePosition = e.GetPosition(_myCanvas);
Debug.WriteLine($"New Position: {canvasRelativePosition}");
Canvas.SetTop(_myRect, canvasRelativePosition.Y - _start.Y);
Canvas.SetLeft(_myRect, canvasRelativePosition.X - _start.X);
}
}
private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_myRect.ReleaseMouseCapture();
this.Cursor = Cursors.Arrow;
}
private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_start = e.GetPosition(_myRect);
Debug.WriteLine($"Start Position: {_start}");
Cursor = Cursors.Hand;
_myRect.CaptureMouse();
}
}
如果您希望变换影响布局,则必须使用 LayoutTransofrm
。 RenderTransform
只改变外观。
Any transformations associated with an elements LayoutTransform property will have an impact on the subsequent Measure and Arrange steps. Whereas a RenderTransform will not have any impact on the layout process and will only effect rendering.
阅读更多here。
但是,LayoutTransform
忽略了 TranslateTransform
LayoutTransform ignores TranslateTransform operations. This is because the layout system behavior for child elements of a FrameworkElement auto-corrects any offsets to the position of a scaled or rotated element into the layout and coordinate system of the parent element.
阅读更多here
也就是说,要实现元素的移动,不能使用Transforms
。您可以尝试手动更改元素的位置(Margin
、Canvas.Left/Right
或其他想法)。