我在Windows 10(UWP)中实现了一个UI,其中的元素可以通过拖放从菜单区域移动到ScrollView区域,也可以将元素从ScrollView移回菜单区域。当元素从菜单移动到ScrollView时,元素将作为菜单的子项删除,并作为子项添加到ScrollView的子项。
但是当我尝试将元素移回时,它们会在菜单后面呈现。我已经玩了z索引和元素在XAML中的顺序并进行了测试,以便在运行时删除并重新添加ScrollView以将其置于顶部,但没有运气。
ScrollView子项之类的接缝不会在视图外部绘制?关于如何解决这个问题的任何建议?
以下是一些说明问题的示例代码:
<Page x:Class="ScrollViewTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ScrollViewTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="Transparent"
Height="200"
Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1"
Canvas.ZIndex="1"
Background="Transparent">
<Canvas Background="Transparent"
Height="0"
Width="0"
VerticalAlignment="Top"
HorizontalAlignment="Left">
<Border Canvas.Left="-25"
Canvas.Top="100"
BorderThickness="2"
BorderBrush="Red"
Width="50"
Height="50"></Border>
</Canvas>
</Grid>
<ScrollViewer Grid.Column="0"
VerticalScrollMode="Enabled"
Canvas.ZIndex="2"
Background="Transparent">
<Canvas Background="Transparent"
Height="0"
Width="0"
VerticalAlignment="Top"
HorizontalAlignment="Left">
<Border Canvas.Left="75"
BorderThickness="2"
BorderBrush="Blue"
Width="50"
Height="50"></Border>
</Canvas>
</ScrollViewer>
</Grid>
结果,我希望蓝色边框显示在网格顶部
答案 0 :(得分:0)
看起来像ScrollView的孩子不在视图之外画画?
这是因为Grid
的内容具有有限的大小,这正是其自身的大小,但ScrollViewer
的内容没有有限的大小,因为它是可滚动的,而不是像{ {1}},Grid
的子元素将始终在其中呈现。
...,我希望蓝色边框显示在网格顶部
老实说,我认为使用ScrollViewer
来实现不同父级之间的拖放操作不是正确的方向。 Canvas.ZIndex值由设置值的最直接的父Canvas元素解释。该值用于在子元素重叠的情况下显式定义绘制顺序。在这种情况下,您的Canvas.ZIndex
和Grid
具有相同的父级,但ScrollViewer
具有不同的父级。
在这里,我可以为您提供一种实现此功能的方法:
Canvas
代码背后:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="rootGrid"
PointerPressed="rootGrid_PointerPressed"
PointerReleased="rootGrid_PointerReleased">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Canvas x:Name="canvas" Grid.Column="1" Background="Wheat">
<Border BorderThickness="2" BorderBrush="Red" Width="50" Height="50" />
<Ellipse Width="50" Height="50" VerticalAlignment="Top" Fill="Red" />
</Canvas>
<ScrollViewer x:Name="scrollViewer" Grid.Column="0"
VerticalScrollMode="Enabled" VerticalScrollBarVisibility="Hidden"
Background="LightBlue">
<Canvas Width="100" x:Name="canvasInsideScrollViewer">
<Border BorderThickness="2" BorderBrush="Blue" Width="50" Height="50" VerticalAlignment="Bottom" />
</Canvas>
</ScrollViewer>
</Grid>
如您所见,我将第二列中的public Page20()
{
this.InitializeComponent();
this.Loaded += Page20_Loaded;
}
private void Page20_Loaded(object sender, RoutedEventArgs e)
{
gridRect = canvas.TransformToVisual(rootGrid).TransformBounds(new Rect(0.0, 0.0, canvas.ActualWidth, canvas.ActualHeight));
scrollViewerRect = scrollViewer.TransformToVisual(rootGrid).TransformBounds(new Rect(0.0, 0.0, scrollViewer.ActualWidth, scrollViewer.ActualHeight));
}
private Rect gridRect;
private Rect scrollViewerRect;
private FrameworkElement MoveElement;
private void rootGrid_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var pointer = e.GetCurrentPoint(rootGrid);
if (gridRect.Left <= pointer.Position.X && pointer.Position.X <= gridRect.Right &&
gridRect.Top <= pointer.Position.Y && pointer.Position.Y <= gridRect.Bottom)
{
foreach (var childElement in canvas.Children)
{
var element = childElement as FrameworkElement;
Rect childBounds = element.TransformToVisual(rootGrid).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
if (childBounds.Left <= pointer.Position.X && pointer.Position.X <= childBounds.Right &&
childBounds.Top <= pointer.Position.Y && pointer.Position.Y <= childBounds.Bottom)
{
MoveElement = element;
canvas.Children.Remove(element);
}
}
}
else if (scrollViewerRect.Left <= pointer.Position.X && pointer.Position.X <= scrollViewerRect.Right &&
scrollViewerRect.Top <= pointer.Position.Y && pointer.Position.Y <= scrollViewerRect.Bottom)
{
foreach (var childElement in canvasInsideScrollViewer.Children)
{
var element = childElement as FrameworkElement;
Rect childBounds = element.TransformToVisual(rootGrid).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
if (childBounds.Left <= pointer.Position.X && pointer.Position.X <= childBounds.Right &&
childBounds.Top <= pointer.Position.Y && pointer.Position.Y <= childBounds.Bottom)
{
MoveElement = element;
canvasInsideScrollViewer.Children.Remove(element);
}
}
}
}
private void rootGrid_PointerReleased(object sender, PointerRoutedEventArgs e)
{
var pointer = e.GetCurrentPoint(rootGrid);
if (MoveElement != null)
{
if (gridRect.Left <= pointer.Position.X && pointer.Position.X <= gridRect.Right &&
gridRect.Top <= pointer.Position.Y && pointer.Position.Y <= gridRect.Bottom)
{
var canvasPointer = e.GetCurrentPoint(canvas);
canvas.Children.Add(MoveElement);
Canvas.SetLeft(MoveElement, canvasPointer.Position.X);
Canvas.SetTop(MoveElement, canvasPointer.Position.Y);
}
else if (scrollViewerRect.Left <= pointer.Position.X && pointer.Position.X <= scrollViewerRect.Right &&
scrollViewerRect.Top <= pointer.Position.Y && pointer.Position.Y <= scrollViewerRect.Bottom)
{
var scrollviewPointer = e.GetCurrentPoint(canvasInsideScrollViewer);
canvasInsideScrollViewer.Children.Add(MoveElement);
Canvas.SetLeft(MoveElement, scrollviewPointer.Position.X);
Canvas.SetTop(MoveElement, scrollviewPointer.Position.Y);
}
}
MoveElement = null;
}
更改为Grid
,因此可以将该元素作为鼠标点呈现在绝对位置。这是我的演示的渲染图像:
这里最令人困惑的部分是你要在不同的父控件之间翻译Canvas
,但是如果你将UIElement
s(你想要拖放)放在{{1}中}},您的Border
,rootGrid
,Grid
将拥有相同的父级,然后您可以关注CustomBehaviorControl的XAMLBehaviorsSample来完成拖动 - 和 - 放弃工作。