WinRT中實現元素拖拉效果

前面有一篇博客涉及到手勢和指針的用法,其中就有利用手勢進行元素的拖拉操作,主要是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事件裏纔去調用共通函數,這下應該就不會出

錯了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章