如何让我的 Rectangle 像对 mouse/pointer 事件那样对触摸事件做出反应?
How can I make my Rectangle react to touch events like it does for mouse/pointer events?
在我的 MainPage 上,我有一个 Stackpanel 充满了五颜六色的矩形,它们都以边距设置为 (0,5,0,5) 开头。我想允许用户仅水平移动这些矩形。由于矩形没有鼠标事件,我使用指针来实现这一点。流程是:用户点击 Rectangle 使其 select,光标改变以给用户视觉提示,用户向左或向右拖动 Rectangle。 (请注意,如果重要的话,Stackpanel 确实有一个垂直滚动查看器)。这是我的 C# 代码:
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);
}
}
此代码非常适合鼠标,但当我尝试将其用于触摸时,我必须按住鼠标才能开始拖动,即便如此,矩形在保持原状之前也只移动了几个单位。我不确定行为为何不同。
此代码的另一个问题是,如果矩形足够窄以至于当我快速拖动时矩形跟不上光标,当光标离开矩形边界时它会停止拖动。比触摸不起作用小得多的问题,但还是有点烦人。
听起来 ScrollViewer 正在捕获触摸事件以进行自己的滚动。除了手动处理操作,您还可以使用 Xaml 的操作引擎来注册操作事件。这既更容易编码又更高效。它默认适用于触摸和鼠标。
<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)。
我在我的博客条目 Where did all my gestures go? If you really want to handle the pointer events yourself I discuss how to disable the ScrollViewer during dragging. You can handle the case where the finger moves faster than the target by capturing the pointer 中讨论了 ScrollViewer 接管指针处理。如果您处理操作事件,则不需要这样做。
在我的 MainPage 上,我有一个 Stackpanel 充满了五颜六色的矩形,它们都以边距设置为 (0,5,0,5) 开头。我想允许用户仅水平移动这些矩形。由于矩形没有鼠标事件,我使用指针来实现这一点。流程是:用户点击 Rectangle 使其 select,光标改变以给用户视觉提示,用户向左或向右拖动 Rectangle。 (请注意,如果重要的话,Stackpanel 确实有一个垂直滚动查看器)。这是我的 C# 代码:
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);
}
}
此代码非常适合鼠标,但当我尝试将其用于触摸时,我必须按住鼠标才能开始拖动,即便如此,矩形在保持原状之前也只移动了几个单位。我不确定行为为何不同。
此代码的另一个问题是,如果矩形足够窄以至于当我快速拖动时矩形跟不上光标,当光标离开矩形边界时它会停止拖动。比触摸不起作用小得多的问题,但还是有点烦人。
听起来 ScrollViewer 正在捕获触摸事件以进行自己的滚动。除了手动处理操作,您还可以使用 Xaml 的操作引擎来注册操作事件。这既更容易编码又更高效。它默认适用于触摸和鼠标。
<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)。
我在我的博客条目 Where did all my gestures go? If you really want to handle the pointer events yourself I discuss how to disable the ScrollViewer during dragging. You can handle the case where the finger moves faster than the target by capturing the pointer 中讨论了 ScrollViewer 接管指针处理。如果您处理操作事件,则不需要这样做。