2016-09-12 2 views
0

Im, реализующий пользовательский интерфейс в Windows 10 (UWP) с элементами, которые можно перемещать с помощью перетаскивания из области меню в область ScrollView, также необходимо перемещать элементы обратно в область меню из ScrollView. Когда элемент перемещается из меню в ScrollView, элемент удаляется как дочерний элемент меню и добавляется в качестве дочернего элемента дочернему элементу ScrollView.Render/draw child of Scrollview вне области прокрутки

Но когда я пытаюсь переместить элементы назад, они отображаются за меню. Я играл с индексом z и порядком элементов в XAML и тестировал удаление и повторное добавление 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

Похоже, что дети ScrollView не выходят за пределы представления?

Это происходит потому, что содержание Grid имеет ограниченный размер, который точно размер сам по себе, но содержание ScrollViewer не имеет ограниченный размер, так как это свитка возможность, а не как Grid, дочерний элемент a ScrollViewer всегда будет отображаться внутри него.

..., я хочу синие границы будут показаны на верхней части сетки

Чтобы быть честно, я думаю, что это не правильное направление, чтобы использовать Canvas.ZIndex реализовать перетаскивание жест между разными родителями. Значение Canvas.ZIndex интерпретируется самым непосредственным родительским элементом Canvas, из которого установлено значение. Значение используется для явного определения порядка рисования в случаях, когда дочерние элементы перекрываются. В этом случае ваши Grid и ScrollViewer имеют один и тот же родительский элемент, но у Canvas s есть разные родительские.

Здесь я могу дать вам метод для реализации этой функции: за

<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, так элемент может отображаться в абсолютном положении в качестве точки мыши.Вот рендеринг изображение моих демо: enter image description here

Здесь наиболее запутанная часть является то, что вы хотите перевести UIElement между различным материнским управлением, но если вы кладете Border с (который вы хотите перетащить и падение) также в rootGrid, ваш Grid, ScrollViewer, Border s будет иметь один и тот же родительский элемент, после чего вы сможете выполнить CustomBehaviorControl из XAMLBehaviorsSample, чтобы завершить работу по перетаскиванию.

+0

Хорошо, спасибо за пояснение по z-index. Я понимаю, что это может быть не лучшее решение для реализации функции перетаскивания, которую я хочу. Что может быть непонятно из моего вопроса, так это то, что я хочу, чтобы элементы были видны при перетаскивании, вот в чем проблема. –

+0

@JonatanBlom, но можно ли его опустить и сбросить в одном и том же родительском элементе управления? Это не будет иметь никакого значения только с предоставленного макета. –