Silverlight对象拖动总结

  在Silverlight中,要实现拖动对象的功能最简单的方式是采用Canvas做为父容器,通过动态的改变元素的附加属性Top、Left即可实现拖动同能。如图所示:

下例所示:

  XAML:

复制代码
<UserControl x:Class="DragExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="500" d:DesignWidth="600">

    <Canvas x:Name="LayoutRoot" Background="Gray">
        <Ellipse x:Name="ellipse" Canvas.Left="300" Canvas.Top="300" Width="100" Height="100"
                 Stroke="YellowGreen"  Fill="White" StrokeThickness="5" 
                 MouseLeftButtonDown="ellipse_MouseLeftButtonDown" 
                 MouseMove="ellipse_MouseMove" 
                 MouseLeftButtonUp="ellipse_MouseLeftButtonUp"></Ellipse>
    </Canvas>
</UserControl>
复制代码

  CS:

复制代码
 public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 标识是否可以拖动对象
        /// </summary>
        private bool isDrag = false;

        private void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            isDrag = true;
            ellipse.CaptureMouse();
        }

        private void ellipse_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrag)
            {
                Point position = e.GetPosition(LayoutRoot);
  
//通过绝对位置定位 Canvas.SetLeft(ellipse, position.X); Canvas.SetTop(ellipse, position.Y); } }
private void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { isDrag = false; } }
复制代码

运行效果:

 

通过使用,即可发现:在体验方面不是很逼真,鼠标指针在移动的过程中,始终处于圆的左上角,即(Left,Top)坐标处。那么如何完善,使鼠标不乱处于圆的任何位置,都能表现出真实的移动过程。可以计算相对移动位置,即可解决。演示图:

如下所示:

复制代码
public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 标识是否可以拖动对象
        /// </summary>
        private bool isDrag = false;

        private Point StartPoint;
        private Point EndPoint;

        private void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            isDrag = true;
            StartPoint = e.GetPosition(LayoutRoot);
            ellipse.CaptureMouse();
        }

        private void ellipse_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrag)
            {
                EndPoint = e.GetPosition(LayoutRoot);

                //计算X、Y轴起始点与终止点之间的相对偏移量
                   double y = EndPoint.Y - StartPoint.Y;
                double x = EndPoint.X - StartPoint.X;

                Point position = new Point((double)Canvas.GetLeft(ellipse), (double)Canvas.GetTop(ellipse));

                //计算(Left,Top)坐标相对移动的目标坐标位置
                   position.X = position.X + x;
                position.Y = position.Y + y;

                Canvas.SetLeft(ellipse, position.X);
                Canvas.SetTop(ellipse, position.Y);

                StartPoint = EndPoint;
            }
        }

        private void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isDrag = false;
        }
    }
复制代码

运行效果:

 

  以上是通过Canvas作为容器,实现元素拖动的功能,但是,使用Canvas作为父容器有一个缺陷就是:子元素不能够自动水平垂直居中显示, 需要一定的数学计算分析才能够居中,如果以当前圆所在位置的圆心为坐标,实现放大缩小功能,而不是以(Left,Top)为圆放大缩小目标点,有什么好的 解决方案??

  第二种方法,可以通过动态计算Margin的Left、Top、Right、Bottom设置的值即可实现多动功能。

  以Grid为父容器,XAML:

复制代码
<Grid x:Name="LayoutRoot" Background="Gray">
        <Ellipse x:Name="ellipse" Width="100" Height="100"
                 Stroke="YellowGreen"  Fill="White" StrokeThickness="5" 
                 MouseLeftButtonDown="ellipse_MouseLeftButtonDown" 
                 MouseMove="ellipse_MouseMove" 
                 MouseLeftButtonUp="ellipse_MouseLeftButtonUp"></Ellipse>
    </Grid>
复制代码

  CS:

复制代码
public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 标识是否可以拖动对象
        /// </summary>
        private bool isDrag = false;

        private Point StartPoint;
        private Point EndPoint;

        private void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            isDrag = true;
            StartPoint = e.GetPosition(LayoutRoot);
            ellipse.CaptureMouse();
        }

        private void ellipse_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrag)
            {
                EndPoint = e.GetPosition(LayoutRoot);

                //计算X、Y轴起始点与终止点之间的相对偏移量
                   double y = EndPoint.Y - StartPoint.Y;
                double x = EndPoint.X - StartPoint.X;

                Thickness margin = ellipse.Margin;

                //计算新的Margin
                Thickness newMargin = new Thickness()
                {
                    Left = margin.Left + x,
                    Top = margin.Top + y,
                    Right = margin.Right - x,
                    Bottom = margin.Bottom - y
                };

                ellipse.Margin = newMargin;

                StartPoint = EndPoint;
            }
        }

        private void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isDrag = false;
        }
    }
复制代码

运行效果:

 

  第三种方案:利用Expression Blend 4的MouseDragElementBehavior,将此附加到元素上即可实现自由拖动。以上是对Silverlight拖动的总结,还有其他方案?

转载于:https://www.cnblogs.com/iwangjun/archive/2012/07/03/2575428.html