有趣的是,您提到了 ScrollViewer,因为这让我想到了使用 ScrollViewer 在其他内容前面放置一个类似前景窗口的控件,而且相当简单。
在您的页面内 - 放置一个延伸到整个应用窗口大小的ScrollViewer(通过将VerticalAlignment 和HorizontalAlignment 都设置为Stretch),它有一个Panel,就像Canvas或 Grid 在其中并将 window/UserControl 放在其中 - 就像下面代码中的 Rectangle 一样。通过将-ScrollMode/-ScrollBarVisibility 值和面板大小设置为大于ScrollViewer's ViewportWidth 和ViewportHeight,确保ScrollViewer 可以双向滚动。您应该在ScrollViewer 和其中的窗口上处理SizeChanged 事件,并将面板的Width 和Height 设置为类似
panel.Width = scrollViewer.ViewportWidth * 2 - window.ActualWidth;
panel.Height = scrollViewer.ViewportHeight * 2 - window.ActualWidth;
现在一切都应该可以通过触摸滚动了。剩下的问题是根据窗口上的Pointer- 事件处理鼠标输入。
XAML
<Page
x:Class="DraggableWindow.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DraggableWindow"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button
Content="Button"
HorizontalAlignment="Left"
Height="99"
Margin="112,101,0,0"
VerticalAlignment="Top"
Width="119" />
<Button
Content="Button"
HorizontalAlignment="Left"
Height="147"
Margin="985,389,0,0"
VerticalAlignment="Top"
Width="262" />
<Button
Content="Button"
HorizontalAlignment="Left"
Height="147"
Margin="403,581,0,0"
VerticalAlignment="Top"
Width="262" />
<Button
Content="Button"
HorizontalAlignment="Left"
Height="147"
Margin="112,277,0,0"
VerticalAlignment="Top"
Width="262" />
<Button
Content="Button"
HorizontalAlignment="Left"
Height="147"
Margin="682,129,0,0"
VerticalAlignment="Top"
Width="262" />
<Button
Content="Button"
HorizontalAlignment="Left"
Height="147"
Margin="551,371,0,0"
VerticalAlignment="Top"
Width="262" />
<ScrollViewer
x:Name="scrollViewer"
SizeChanged="OnScrollViewerSizeChanged"
Background="{x:Null}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollMode="Auto"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
IsHorizontalRailEnabled="False"
IsVerticalRailEnabled="False">
<Canvas
x:Name="panel">
<Rectangle
x:Name="window"
SizeChanged="OnWindowSizeChanged"
PointerPressed="OnWindowPointerPressed"
PointerMoved="OnWindowPointerMoved"
PointerReleased="OnWindowPointerReleased"
Fill="LightGray"
Width="200"
Height="150"/>
</Canvas>
</ScrollViewer>
</Grid>
</Page>
C#
使用 Windows.Devices.Input;
使用 Windows.Foundation;
使用 Windows.UI.Xaml;
使用 Windows.UI.Xaml.Controls;
使用 Windows.UI.Xaml.Input;
namespace DraggableWindow
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private uint pointerId;
private Point lastPoint;
private void OnWindowPointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
{
window.CapturePointer(e.Pointer);
this.pointerId = e.Pointer.PointerId;
this.lastPoint = e.GetCurrentPoint(window).Position;
}
}
private void OnWindowPointerMoved(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.IsInContact &&
e.Pointer.PointerId == pointerId)
{
var point = e.GetCurrentPoint(window).Position;
this.scrollViewer.ChangeView(
this.scrollViewer.HorizontalOffset - point.X + lastPoint.X,
this.scrollViewer.VerticalOffset - point.Y + lastPoint.Y,
null,
true);
}
}
private void OnWindowPointerReleased(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == pointerId)
{
window.ReleasePointerCapture(e.Pointer);
}
}
private void OnScrollViewerSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateWindowingLayout();
}
private void OnWindowSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateWindowingLayout();
}
private void UpdateWindowingLayout()
{
this.panel.Width = this.scrollViewer.ViewportWidth * 2 - 0.0 * this.window.ActualWidth;
this.panel.Height = this.scrollViewer.ViewportHeight * 2 - 0.5 * this.window.ActualHeight;
Canvas.SetLeft(this.window, this.scrollViewer.ViewportWidth - 0.5 * this.window.ActualWidth);
Canvas.SetTop(this.window, this.scrollViewer.ViewportHeight - 0.5 * this.window.ActualHeight);
}
}
}
哦,让这一切变得动态 - 将其包装在 UserControl 中以处理那里的事件并将其放入 Popup 中。当我有机会时,我会看到将所有这些都包装在一个可重用的控件中,因为我的可视化树调试器叠加层也需要类似的东西。