一步一步学Silverlight 2系列(5):实现简单的拖放功能

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章带您快速进入Silverlight 2开发。

本文为系列文章第五篇,利用前面讲过的鼠标事件处理实现简单的拖放功能。

准备XAML

在实现拖放功能中,分为三个步骤:

1.按下鼠标,触发MouseLeftButtonDown事件,选择要拖动的对象。

2.移动鼠标,触发MouseMove事件,移动选择的对象。

3.放开鼠标,触发MouseLeftButtonUp事件,停止捕捉事件。

做一个简单的界面,用一个按钮来显示拖放,如下XAML声明:

<Canvas Background="#46461F">
    <Button 
       MouseLeftButtonDown="OnMouseDown" 
       MouseMove="OnMouseMove"
       MouseLeftButtonUp="OnMouseUp" 
       Canvas.Left="50" Canvas.Top="50" Background="Red"
       FontSize="18"
       Width="160" Height="80">
        <Button.Content>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
                        VerticalAlignment="Center">
                <Image Source="smile_6.png"></Image>
                <TextBlock Text="拖动我" VerticalAlignment="Center" Margin="10"></TextBlock>
            </StackPanel>
        </Button.Content>
    </Button>
</Canvas>

这里为了界面显示效果,使用了控件模板,后续会专门讲到。

开始拖放操作

开始拖放操作,实现MouseLeftButtonDown事件处理程序,用两个全局变量来记录当前鼠标的位置和鼠标是否保持移动。

bool trackingMouseMove = false;
Point mousePosition;

void OnMouseDown(object sender, MouseButtonEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    mousePosition = e.GetPosition(null);
    trackingMouseMove = true;
    if (null != element)
    {
        element.CaptureMouse();
        element.Cursor = Cursors.Hand;
    }
}

移动对象

移动对象,实现MouseMove事件处理程序,计算元素的位置并更新,同时更新鼠标的位置。

void OnMouseMove(object sender, MouseEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    if (trackingMouseMove)
    {
        double deltaV = e.GetPosition(null).Y - mousePosition.Y;
        double deltaH = e.GetPosition(null).X - mousePosition.X;
        double newTop = deltaV + (double)element.GetValue(Canvas.TopProperty);
        double newLeft = deltaH + (double)element.GetValue(Canvas.LeftProperty);

        element.SetValue(Canvas.TopProperty, newTop);
        element.SetValue(Canvas.LeftProperty, newLeft);

        mousePosition = e.GetPosition(null);
    }
}

完成拖放操作

完成拖放操作,实现MouseLeftButtonUp事件处理程序。

void OnMouseUp(object sender, MouseButtonEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    trackingMouseMove = false;
    element.ReleaseMouseCapture();

    mousePosition.X = mousePosition.Y = 0;
    element.Cursor = null;
}

效果显示

最终,完成后的效果如下

TerryLee_Silverlight2_0035

拖动按钮

TerryLee_Silverlight2_0036

结束语

本文实现了一个简单的拖放功能(示例来自于Silverlight 2 SDK),点击下载文本示例代码。

下一篇:一步一步学Silverlight 2系列(6):键盘事件处理

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Tag标签: Silverlight,XAML
posted @ 2008-03-08 00:40 TerryLee 阅读(8928) 评论(48)  编辑 收藏 网摘 所属分类: [03]  银光点亮世界

  回复  引用    
#1楼 2008-03-08 23:34 | ohaiyo [未注册用户]
GetPosition(relativeTo)函数里的参数是表示位置是相对于relativeTo参数对象的

你上面的实例里GetPosition(null),这个怎样理解的?
  回复  引用    
#2楼 2008-03-08 23:45 | ohaiyo [未注册用户]
明了
To specify the object relative to the overall  Silverlight coordinate system, set the relativeTo parameter to null.
  回复  引用  查看    
#3楼 2008-03-20 00:28 | Cat Chen      
Silverlight2.0也没有内置拖放支持,这点让人比较失望……
  回复  引用  查看    
#4楼 [楼主]2008-03-20 09:06 | TerryLee      
@Cat Chen
是啊,现在只能是靠鼠标事件来控制元素的位置实现拖放
  回复  引用  查看    
#5楼 2008-04-25 13:47 | aito      
Silverlight 2 SDK 有没有中文的了?可不可以给个地址出来呢?
  回复  引用  查看    
#6楼 2008-06-16 18:35 | 飄lá┽蕩去      
在beta2版本下不成功啊,应该怎么做啊?
  回复  引用  查看    
#7楼 2008-06-17 22:55 | 房客      
冇错,在beta2中,好像这个实现不了。
  回复  引用  查看    
#8楼 [楼主]2008-06-17 22:58 | TerryLee      
@房客
该系列文章的环境是Beta 1!
  回复  引用  查看    
#9楼 2008-06-17 23:00 | 房客      
嗯。我知道,我只是说出你的例子在Beta2中可能出现的问题,让我们后来学习的人不要在beta2中死钻这个问题,我调了半天才发现的。

我调试了下,好像是在程序中不可以设置Canvas的属性。比如:
SetValue(Canvas.LeftProperty, 100);

  回复  引用  查看    
#10楼 [楼主]2008-06-18 00:00 | TerryLee      
@房客
Beta 2中SetValue方法修改过了,不可以直接指定一个double类型的值,需要转换为Object对象才行。
  回复  引用  查看    
#11楼 [楼主]2008-06-18 00:11 | TerryLee      
  回复  引用  查看    
#12楼 2008-06-20 15:59 | 飄lá┽蕩去      
使用了控件模板之后,事件怎么触发不了了???
  回复  引用    
#13楼 2008-06-24 14:18 | allen.wang [未注册用户]
OnMouseDown和OnMouseUp在Beta2的环境下无法触发,不知道Beta1有没有这个问题?但OnMouseMove可以触发,非常奇怪!
  回复  引用    
#14楼 2008-06-24 17:24 | cx19800421 [未注册用户]
确实OnMouseDown和OnMouseUp在Beta2的环境下无法触发
  回复  引用    
#15楼 2008-06-25 09:16 | botsing [未注册用户]
最近开始看这个系列的教程,我用的是beta2的,好像mousedown和mouseup在beta2中并不是完全不能用的,Button组件是不行的,不过我在一个IMAGE组件的这两个事件添加了这些代码之后,可以实现拖动的
难道这个跟控件类型有关?
  回复  引用  查看    
#16楼 2008-06-25 22:53 | Goumh      
没错,在beta2中,Button 控件不能实现拖放操作,但是其它控件似乎可以,比TextBlock 、Image 等。
  回复  引用  查看    
#17楼 [楼主]2008-06-26 09:56 | TerryLee      
@Goumh
不是不可以,是在事件处理机制上有些变化。。,有空我会详细解释一下。
  回复  引用  查看    
#18楼 2008-06-26 19:27 | 阿胜      
貌似在BETA 2中,按钮没有MouseLeftButtonDown,和MouseLeftButtonUp事件吧。
  回复  引用    
#19楼 2008-06-26 21:12 | botsing [未注册用户]
@阿胜
事件同样是存在的,只是添加了事件代码之后却不会被触发

等待楼主的讲解吧
  回复  引用  查看    
#20楼 2008-06-27 20:38 | 阿胜      
@botsing
呵呵。是的。
  回复  引用    
#21楼 2008-07-15 15:19 | garf [未注册用户]
能说一下这个网站中silverlight插件上边的那个拖动的实现思路吗
http://www.flowerskc.com/FlowersKC/WebPages/Weddings.aspx
  回复  引用  查看    
#22楼 [楼主]2008-07-21 10:22 | TerryLee      
@garf
这个似乎也没有多少难的,主要在鼠标事件里面控制一下动画,可以在Silverlight.net网站上找到类似的例子。。。
  回复  引用    
#23楼 2008-08-20 10:55 | xhz [未注册用户]
buttong在Beta2中不能拖动了,改成Image就可以拖动了
================================================
<UserControl....>
<Canvas Background="#46461F">
<Image Source="smile_6.png"
MouseLeftButtonDown="OnMouseDown"
MouseMove="OnMouseMove"
MouseLeftButtonUp="OnMouseUp"/>
</Canvas>
</UserControl>
  回复  引用    
#24楼 2008-08-22 17:56 | ChMal [未注册用户]
beta2 中用Button的子控件StackPanel的MouseLeftButtonUp和MouseLeftButtonDown事件就可以实现了。因为控件的事件是向上传递的。
  回复  引用    
#25楼 2008-08-22 18:01 | ChMal [未注册用户]
@TerryLee
Beta 2中SetValue方法修改过了,不可以直接指定一个double类型的值,需要转换为Object对象才行。
这个好像直接传递double值,也可以执行。
  回复  引用    
#26楼 2008-08-26 18:50 | 卡索! [未注册用户]
回各位好朋友!
在进行阅读楼主的博文时,在实际的操作中确实出现了在Beta2版本中Button无MouseLeftButtonDown和MouseLeftButtonUp这两个事件。
如果把Button换成StackPanel,博主的代码不用进行修改是可以执行成功的!
有遇到和我类似问题的朋友们可以尝试测试下!

  回复  引用    
#27楼 2008-09-11 11:18 | Nick Lee [未注册用户]
把MouseLeftButtonDown和MouseLeftButtonUp这两个事件移到StackPanel下, 确实可以运行. 但是偶尔会无法触发事件而拖不动.要多按几下才又拖的动. 有人知道为何吗?

  回复  引用  查看    
#28楼 [楼主]2008-09-17 00:58 | TerryLee      
@Nick Lee
可能是事件路由的问题。
  回复  引用    
#29楼 2008-09-22 11:29 | snowblue [未注册用户]
@Nick Lee
因为StackPanel并不是平铺到整个Button控件上,只是紧凑包围了内容,你把鼠标点在内容上,如图片、文字,就可以执行事件了,如果点在Button的内容外面的空白区域,那些不是StackPanel的覆盖范围,则不执行事件
  回复  引用    
#30楼 2008-10-05 21:04 | XiiL [未注册用户]
在Beta2中,Button(还有一些控件)会把发生在自己身上的事件截获,而不会再向上传递给自己的父控件.
  回复  引用    
#31楼 2008-10-06 02:08 | XiiL [未注册用户]
应该是Button不再响应MouseLeftButtonDown(UP)事件.
  回复  引用  查看    
#32楼 2008-11-07 15:43 | 戏水      
CaptureMouse()

ReleaseMouseCapture()
是做什么呢? 我注释掉这两行 貌似也没啥影响啊?
会军兄给解释解释吧
  回复  引用  查看    
#33楼 [楼主]2008-11-07 23:39 | TerryLee      
@戏水
捕捉或者释放鼠标。

PS:不太确定在RTW下是不是还有它们?
  回复  引用    
#34楼 2008-11-16 06:37 | 风绪 [未注册用户]
为什么需要捕捉鼠标呢?
不捕捉也可以移动,是否是版本不同的原因?
Point mousePoint;
bool move;

private void panel_MouseMove(object sender, MouseEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;

if (move)
{
Canvas.SetLeft(element, Canvas.GetLeft(element) + e.GetPosition(null).X - mousePoint.X);
Canvas.SetTop(element, Canvas.GetTop(element) + e.GetPosition(null).Y - mousePoint.Y);

mousePoint = e.GetPosition(null);
}
}

private void panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
mousePoint = e.GetPosition(null);
move = true;
}

private void panel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
move = false;
}
  回复  引用    
#35楼 2008-12-02 13:39 | u father [未注册用户]
nnd,这个东西能动吗?
  回复  引用    
#36楼 2008-12-02 19:35 | 冻结2 [未注册用户]
@风绪
为什么需要捕捉鼠标/释放捕获鼠标呢?

1.在鼠标按下的时候(MouseLeftButtonDown)执行捕获鼠标(CaptureMouse),这就好比告诉鼠标“当前鼠标正在对该对象操作”,以至于鼠标移动的时候(MouseMove),既便脱离该对象,也依然会出发该对象的MouseMove事件。

2.同理,鼠标松开的时候(MouseLeftButtonUp)必须要释放捕获的鼠标,以便鼠标可以操作其它对象,这就好比告诉鼠标“你不要操作我了,你可以喝咖啡去了”,这样鼠标再移动的时候(MouseMove),也不会再操作该对象。

你可以做个简单的实验,不加捕获鼠标/释放捕获鼠标,鼠标按下后,迅速移动鼠标,你会看到什么现象?是不是鼠标离开对象就失去作用了?
  回复  引用  查看    
#37楼 2008-12-03 13:02 | Z-Suker      
会军大哥,我装的是SilverLight2.0的beta2版~怎么你第5章的例子运行不了呢???感觉beta1和beta2好多地方有差别啊.......会军大哥,帮帮忙说下怎么在beta2版里让button移动啊~~~~~~~~~~
  回复  引用    
#38楼 2008-12-04 01:36 | 冻结2 [未注册用户]
@Z-Suker
sl2.0bate2和sl2.0正式版的button都不能移动了,会军大哥也说了这是事件路由的问题,
你刻意把button改为Rectangle,Ellipse或者其他控件,

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-08 14:19 编辑过
Google站内搜索



相关文章:


相关搜索:
Silverlight XAML

相关链接: