2015-01-15 1 views
0

На моей главной странице у меня есть Stackpanel, полный разноцветных прямоугольников, и все они начинаются с Margin, установленного в (0,5,0,5). Я хотел бы разрешить пользователю перемещать эти прямоугольники только по горизонтали. Поскольку Rectangles не имеют событий Mouse, я использую указатель для достижения этого. Поток: пользователь нажимает на прямоугольник, чтобы выбрать его, курсор меняется, чтобы дать пользователю визуальный сигнал, пользователь перетаскивает прямоугольник влево или вправо. (Обратите внимание, что Stackpanel имеет вертикальный scrollviewer, если это имеет значение). Вот мой C# код:Как я могу заставить Rectangle реагировать на события, подобные событиям мыши/указателя?

private void Rectangle_FirstClick(object sender, EventArgs e) 
{ 
    // Give rectangle a white border to imply selection 
    Rectangle myControl = sender as Rectangle; 
    myControl.StrokeThickness = 1; 
    myControl.Stroke = new SolidColorBrush(Color.FromArgb(255, 240, 240, 240)); 

    // Provide visual cue to mouse users by changing the pointer immediately 
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.SizeWestEast, 0); 

    // Handle mouse leaving/re-entering the track piece 
    myControl.PointerEntered += MyControl_PointerEntered; 
    myControl.PointerExited += MyControl_PointerExited; 

    // Handle the drag event 
    myControl.PointerPressed += MyControl_PointerPressed; 
    myControl.PointerReleased += MyControl_PointerReleased; 
    myControl.PointerMoved += MyControl_PointerMoved; 
} 

Вот отдельные обработчики событий

bool PossibleDragStart = false; 
Point InitialDragPoint = new Point(0, 0); 

private void MyControl_PointerExited(object sender, PointerRoutedEventArgs e) 
{ 
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.Arrow, 0); 
} 

private void MyControl_PointerEntered(object sender, PointerRoutedEventArgs e) 
{ 
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.SizeWestEast, 0); 
} 

private void MyControl_PointerPressed(object sender, PointerRoutedEventArgs e) 
{ 
    PossibleDragStart = true; 
    InitialDragPoint = e.GetCurrentPoint(sender as Rectangle).Position; 
} 

private void MyControl_PointerReleased(object sender, PointerRoutedEventArgs e) 
{ 
    PossibleDragStart = false; 
} 

private void MyControl_PointerMoved(object sender, PointerRoutedEventArgs e) 
{ 
    // If pointer pressed without release, and then moved, we are dragging 
    if (PossibleDragStart) 
    { 
     Point CurrentDragPoint = e.GetCurrentPoint(AudioTracksRightContainer).Position; 
     StatusBar.Text = CurrentDragPoint.X.ToString(); 

     // Calculate drag offset by subtracting Current Position from Initial Position 
     double SegmentMargin = CurrentDragPoint.X - InitialDragPoint.X; 

     // Move the Rectangle with the pointer drag 
     Rectangle trackSegment = sender as Rectangle; 
     trackSegment.Margin = new Thickness(SegmentMargin, 5, 0, 5); 
    } 
} 

Этот код работает отлично подходит для мыши, но когда я пытаюсь использовать его для прикосновения, я должен нажать-и -hold, чтобы начать перетаскивание, и даже тогда прямоугольник перемещает только несколько единиц, прежде чем оставаться на месте. Я не уверен, почему поведение отличается.

Другая проблема с этим кодом заключается в том, что если прямоугольник достаточно узкий, чтобы при быстром перемещении и прямоугольник не мог идти в ногу с курсором, он перестает перетаскиваться, когда курсор покинул границу прямоугольника. Гораздо меньшая проблема, чем прикосновение, не работает, но немного раздражает.

ответ

1

Похоже, ScrollViewer захватывает события касания, чтобы выполнить собственную прокрутку. Вручную манипулируя манипуляциями вручную, вы можете использовать механизм манипуляции Xaml для регистрации событий манипуляции. Это проще и эффективнее. По умолчанию он будет работать для touch и mouse.

<Rectangle Margin="5" Fill="Orange" Height="100" Width="200" 
      ManipulationMode="TranslateX" 
      ManipulationDelta="Rectangle_ManipulationDelta" 
      > 
    <Rectangle.RenderTransform> 
     <CompositeTransform /> 
    </Rectangle.RenderTransform> 
</Rectangle> 

В методе Rectangle_ManipulationDelta перевести прямоугольник:

private void Rectangle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) 
{ 
    UIElement elem = sender as UIElement; 
    CompositeTransform ct = elem.RenderTransform as CompositeTransform; 

    ct.TranslateX += e.Delta.Translation.X; 
} 

Если вы хотите только переводов вы могли бы использовать TranslateTransform вместо CompositeTransform, или вы могли бы добавить в поворотах и ​​масштабировании.

Подробнее об использовании жестов и манипуляций см. В разделе Quickstart: Touch input (XAML).

Я обсуждаю, как ScrollViewer берет на себя обработку указателя в моей записи в блоге Where did all my gestures go? Если вы действительно хотите обрабатывать события указателя самостоятельно, я обсуждаю, как отключить ScrollViewer во время перетаскивания. Вы можете обрабатывать случай, когда палец движется быстрее цели на capturing the pointer. Это не нужно, если вы обрабатываете события манипуляции.

+0

Спасибо, Роб, отлично работал и упростил код. Я не знал о ManipulationMode, но теперь я знаю :) – Freakishly

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

  • Нет связанных вопросов^_^