前面有一篇博客涉及到手勢和指針的用法,其中就有利用手勢進行元素的拖拉操作,主要是ManipulationDelta:
博客地址: Windows Phone 8.1觸控輸入-----手勢及指針
其實利用手勢ManipulationDelta操作來實現元素拖拉的方法很簡單,很實用。但是一旦要實現頁面中多個控件元素
的拖拉,難免代碼臃腫。其實我們可以抽象出這其中一致的功能代碼,這樣要實現某一個元素的拖拉效果只需調用共
通類中的共有函數即可。
所以下面介紹的是如何封裝成共有的類來進行調用:
(這裏主要是利用PointerPressed,PointerMoved,PointerReleased三個方法)
1.首先是XAML代碼,頁面佈局只要放一個canvas,再在canvas下放一個rectangle
<Page
x:Class="DragDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DragDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Canvas Width="300" Height="300" Background="White">
<Rectangle x:Name="rect" Width="100" Height="100" Fill="Coral"/>
</Canvas>
</Grid>
</Page>
2..CS代碼:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// “空白頁”項模板在 http://go.microsoft.com/fwlink/?LinkId=391641 上有介紹
namespace DragDemo
{
/// <summary>
/// 可用於自身或導航至 Frame 內部的空白頁。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
this.Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
DragHelper.Dragable(rect);
}
/// <summary>
/// 在此頁將要在 Frame 中顯示時進行調用。
/// </summary>
/// <param name="e">描述如何訪問此頁的事件數據。
/// 此參數通常用於配置頁。</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: 準備此處顯示的頁面。
// TODO: 如果您的應用程序包含多個頁面,請確保
// 通過註冊以下事件來處理硬件“後退”按鈕:
// Windows.Phone.UI.Input.HardwareButtons.BackPressed 事件。
// 如果使用由某些模板提供的 NavigationHelper,
// 則系統會爲您處理該事件。
}
}
}
3.共通類的共通函數:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace DragDemo
{
public static class DragHelper
{
public static readonly DependencyProperty IsDraggingProperty = DependencyProperty.RegisterAttached(
"IsDragging", typeof(bool), typeof(DragHelper), new PropertyMetadata(false));
public static readonly DependencyProperty StartLeftProperty = DependencyProperty.RegisterAttached("StartLeft",
typeof(double), typeof(DragHelper), new PropertyMetadata(0.0d));
public static readonly DependencyProperty StartTopProperty = DependencyProperty.RegisterAttached("StartTop",
typeof(double), typeof(DragHelper), new PropertyMetadata(0.0d));
public static readonly DependencyProperty StartPositionProperty =
DependencyProperty.RegisterAttached("StartPosition", typeof(Point), typeof(DragHelper),
new PropertyMetadata(default(Point)));
public static bool Dragable(this UIElement control)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (VisualTreeHelper.GetParent(control) is Canvas)
{
control.PointerPressed += (sender, e) =>
{
control.SetValue(IsDraggingProperty, true);
control.SetValue(StartLeftProperty, Canvas.GetLeft(control));
control.SetValue(StartTopProperty, Canvas.GetTop(control));
control.SetValue(StartPositionProperty, e.GetCurrentPoint(null).Position);
};
var coreWindow = Window.Current.CoreWindow;
coreWindow.PointerMoved += (sender, args) =>
{
if ((bool)control.GetValue(IsDraggingProperty))
{
var currentPosition = args.CurrentPoint.Position;
var startPosition = (Point)control.GetValue(StartPositionProperty);
var deltaX = currentPosition.X - startPosition.X;
var deltaY = currentPosition.Y - startPosition.Y;
var startLeft = (double)control.GetValue(StartLeftProperty);
var startTop = (double)control.GetValue(StartTopProperty);
Canvas.SetLeft(control, startLeft + deltaX);
Canvas.SetTop(control, startTop + deltaY);
}
};
coreWindow.PointerReleased += (sender, args) => control.SetValue(IsDraggingProperty, false);
return true;
}
else
{
return false;
}
}
}
}
推薦鏈接:【WinRT】讓控件飛,WinRT 中實現 web 中的 dragable 效果
上述過程中,我遇到一個問題,我直接在MainPage構造函數中直接調用共通函數,然後就會報錯。後來我想因爲在
其中使用到VisualTreeHelper.GetParent(UIElement...),通過可視化樹操作獲取需要拖拉控件的父元素,但是一旦
頁面還未加載完成就去獲取當然應該會出錯。所以我之後在頁面的load事件裏纔去調用共通函數,這下應該就不會出
錯了。