3

У меня есть проект, который требует перетаскивания пользовательского элемента управления (размещенного внутри сетки) вокруг экрана. Это прекрасно работает на код ниже:Проверьте, находится ли пользовательский контроль в пределах оконных окон

void MyUserControl_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) 
{ 
    var ct = (CompositeTransform) RenderTransform ?? new CompositeTransform {CenterX = 0.5, CenterY = 0.5}; 
     ct.TranslateX += e.Delta.Translation.X; 
     ct.TranslateY += e.Delta.Translation.Y; 
} 

Вопрос заключается в том, что пользовательский элемент управления можно перетаскивать весь путь из области экрана. Чтобы предотвратить это, я попытался пример, показанный здесь: http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx

К сожалению, он использует containingRect.Contains (shapeBounds), тогда как в Windows 8, мы, как ожидается, заменит shapeBounds (это прямоугольник) с точки. Я не уверен, как с этим работать.

Итак, вопрос в том, как мы можем гарантировать, что пользовательский элемент управления или любой UIElement нельзя вытащить из области Window.Current.Bounds в приложении для хранения приложений на окнах 8?

Спасибо.

РЕДАКТИРОВАТЬ: Более подробную информации о структуре XAML:

На главной странице содержит сетку с горизонтальным и вертикальным выравниванием набором, чтобы растянуть. Пользовательские элементы управления добавляются в эту сетку по мере необходимости. Каждый usercontrol имеет родительскую сетку, которая содержит 3 разных вида (полноэкранный, оконный и малый). Представления отображаются по выбору пользователя. Поведение сопротивления должно применяться только при отображении сетки окон. Таким образом, у нас есть это

<Grid> <!-- this is the parent grid on mainpage with horizontal and vertical alignment to stretch--> 
    <Grid> <!-- this is the usercontrol's main grid (added to above grid via code). This grid must be draggable if the below grid is window --> 
     <Grid /> <!-- this is one of the child grids that is shown based on user's choice (fullscreen, window or small view).--> 
    </Grid> 
</Grid> 

У меня нет большого выбора в изменении макета. Используя указанное выше событие ManipulationDelta в usercontrol (которое включено/отключено на основе представленной дочерней сетки), я могу получить поведение перетаскивания, но элемент управления может выйти из оконных границ. Итак, есть ли способ добавить ниже FlickBehavior в WinRTXamlToolkit через код вместо xaml ИЛИ включить/отключить поведение, основанное на некоторых условиях?

<i:Interaction.Behaviors> 
    <views:HeavyFlickBehavior /> 
</i:Interaction.Behaviors> 
+0

Где твой UserControl? в холсте? – Xyroid

+0

Он находится внутри сетки, но может быть перемещен на холст, если использование сетки является проблемой. – Girish

+0

Я думаю, вам нужно вручную проверить, находится ли край пользовательского контроля рядом с привязкой или без использования 'TransformToVisual' и' TransformPoint' – Xyroid

ответ

3

Вы можете проверить FlickBehavior в WinRT XAML Toolkit для примера того, как добиться того, что с родителем Canvas и Canvas.Top/Left свойств вместо RenderTransform, предполагая, что Canvas определяет свои границы.

Вот аннотация:

private void OnAssociatedObjectManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e) 
{ 
    _startPosition = new Point(
     Canvas.GetLeft(this.AssociatedObject), 
     Canvas.GetTop(this.AssociatedObject)); 
} 

private void OnAssociatedObjectManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs manipulationDeltaRoutedEventArgs) 
{ 
    var dx = manipulationDeltaRoutedEventArgs.Cumulative.Translation.X; 
    var dy = manipulationDeltaRoutedEventArgs.Cumulative.Translation.Y; 

    var x = _startPosition.X + dx; 
    var y = _startPosition.Y + dy; 

    if (manipulationDeltaRoutedEventArgs.IsInertial) 
    { 
     while (x < 0 || 
       x > _canvas.ActualWidth - this.AssociatedObject.ActualWidth) 
     { 
      if (x < 0) 
       x = -x; 
      if (x > _canvas.ActualWidth - this.AssociatedObject.ActualWidth) 
       x = 2 * 
        (_canvas.ActualWidth - this.AssociatedObject.ActualWidth) - 
        x; 
     } 

     while (y < 0 || 
       y > _canvas.ActualHeight - this.AssociatedObject.ActualHeight) 
     { 
      if (y < 0) 
       y = -y; 
      if (y > _canvas.ActualHeight - this.AssociatedObject.ActualHeight) 
       y = 2 * (_canvas.ActualHeight - this.AssociatedObject.ActualHeight) - 
        y; 
     } 
    } 
    else 
    { 
     if (x < 0) 
      x = 0; 
     if (x > _canvas.ActualWidth - this.AssociatedObject.ActualWidth) 
      x = _canvas.ActualWidth - this.AssociatedObject.ActualWidth; 
     if (y < 0) 
      y = 0; 
     if (y > _canvas.ActualHeight - this.AssociatedObject.ActualHeight) 
      y = _canvas.ActualHeight - this.AssociatedObject.ActualHeight; 
    } 

    Canvas.SetLeft(this.AssociatedObject, x); 
    Canvas.SetTop(this.AssociatedObject, y); 
} 
+0

Привет, Филипп, спасибо за подробный ответ. Я проведу его позже сегодня и вернусь обратно. Можно ли реализовать то же самое с использованием RenderTransform и Grid в качестве контейнера? – Girish

+0

Да, если ваше преобразование только обновляет свойства X/Y, вы просто обновите его X/Y вместо Canvas.Left/Top. Единственная проблема может заключаться в том, что ваш перетаскиваемый элемент больше, чем контейнер, поскольку это может вызвать обрезку.Я не думаю, что мой код даже влияет на него, поэтому он все равно может упасть или повесить. Просто убедитесь, что вы устанавливаете HorizontalAlignment вашего дочернего элемента влево, VerticalAlignment to Top и Margin равным 0. –

+0

Hi Filip, испробовал вышеупомянутое решение, и он отлично работает, если родительский холст с дочерним uielement. Но у меня есть несколько более сложная проблема. Я отредактировал мой вопрос, чтобы лучше объяснить. – Girish

Смежные вопросы