在Scrollview区域外渲染/绘制Scrollview的子项

时间:2016-09-12 10:23:38

标签: xaml scrollview uwp windows-10-universal uwp-xaml

我在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>

结果,我希望蓝色边框显示在网格顶部

1 个答案:

答案 0 :(得分:0)

  

看起来像ScrollView的孩子不在视图之外画画?

这是因为Grid的内容具有有限的大小,这正是其自身的大小,但ScrollViewer的内容没有有限的大小,因为它是可滚动的,而不是像{ {1}},Grid的子元素将始终在其中呈现。

  

...,我希望蓝色边框显示在网格顶部

老实说,我认为使用ScrollViewer来实现不同父级之间的拖放操作不是正确的方向。 Canvas.ZIndex值由设置值的最直接的父Canvas元素解释。该值用于在子元素重叠的情况下显式定义绘制顺序。在这种情况下,您的Canvas.ZIndexGrid具有相同的父级,但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,因此可以将该元素作为鼠标点呈现在绝对位置。这是我的演示的渲染图像: enter image description here

这里最令人困惑的部分是你要在不同的父控件之间翻译Canvas,但是如果你将UIElement s(你想要拖放)放在{{1}中}},您的BorderrootGridGrid将拥有相同的父级,然后您可以关注CustomBehaviorControlXAMLBehaviorsSample来完成拖动 - 和 - 放弃工作。

相关问题