Silverlight Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)

Silverlight & Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)
原文:Silverlight & Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)

  在Silverlight中自身并没有提供拖放功能的相关实现,要实现拖放功能得借助其事件支持(MouseLeftButtonDown、MouseLeftButtonUp和MouseMove)来完成,实际应用中我们可以通过行为(Behavior)特性将拖放操作封装为行为,这样可达到代码复用的效果。而在Blend中则直接提供了拖放操作行为,它位于Microsoft.Expression.Interactions.dll的Microsoft.Expression.Interactivity.Layout名称空间下。

 

  Silverlight中的拖放操作通常是使用事件驱动动态定位对象的坐标来实现,首先来看看如何通过代码的可编程方式在Silverlight中实现拖放操作,如下代码块:

private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    FrameworkElement element 
= sender as FrameworkElement;
    MousePosition 
= e.GetPosition(null);
    IsMouseCaptured 
= true;
    element.CaptureMouse();
    element.Cursor 
= Cursors.Hand;
}

private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    FrameworkElement element 
= sender as FrameworkElement;
    IsMouseCaptured 
= false;
    element.ReleaseMouseCapture();
    MousePosition.X 
= MousePosition.Y = 0;
    element.Cursor 
= null;
}

private void OnMouseMove(object sender, MouseEventArgs e)
{
    FrameworkElement element 
= sender as FrameworkElement;
    
if (IsMouseCaptured)
    {
        
double Y = e.GetPosition(null).Y - MousePosition.Y;
        
double X = e.GetPosition(null).X - MousePosition.X;

        X 
= X + (double)element.GetValue(Canvas.LeftProperty);
        Y 
= Y + (double)element.GetValue(Canvas.TopProperty);

        element.SetValue(Canvas.LeftProperty, X);
        element.SetValue(Canvas.TopProperty, Y);

        MousePosition 
= e.GetPosition(null);
    }
}

 

  如上定义好的三个方法实现了对象的拖放算法,实际应用中只需要将需要进行拖放移动的对象分别添加MouseLeftButtonDown、MouseLeftButtonUp和MouseMove事件处理就行了。如下示例代码:

attachedElement.MouseLeftButtonDown += (s, e) => OnMouseLeftButtonDown(s, e);
attachedElement.MouseLeftButtonUp 
+= (s, e) => OnMouseLeftButtonUp(s, e);
attachedElement.MouseMove 
+= (s, e) => OnMouseMove(s, e);

 

  按照常规做法我们会将以上相关方法的实现封装为一个基类以达到复用的目的,但本文不推荐使用基类去封装拖放行为,因为Silverlight有专门用于处理对象行为的特性-Behaviors。在Silverlight中System.Windows.Interactivity命名空间下提供了行为的基础框架,我们可以进行自由的扩展行为以实现自己的不同需求。安装Blend后可以在安装目录下找到Microsoft.Expression.Interactivity.dll这个库,这个库提供了一些比较常用的集中行为扩展,在Blend中通过“窗口”--“资产”打开资产面板,选择行为资产就可以查看到Silverlight 3中所提供的扩展行为,如下图: 

         

 

  我们可以将上面实现对象拖放的功能封装为行为以达到代码复用,在Blend中通过“文件”--“新建”菜单项可打开新建对象对话框。

        

 

  Blend新建向导创建的行为提供了一套行为模板,如下代码块:

public class Behavior1 : Behavior<DependencyObject>
{
    
public Behavior1()
    {
        
// 在此点下面插入创建对象所需的代码。

        
//
        
// 下面的代码行用于在命令
        
// 与要调用的函数之间建立关系。如果您选择
        
// 使用 MyFunction 和 MyCommand 的已注释掉的版本,而不是创建自己的实现,
        
// 请取消注释以下行并添加对 Microsoft.Expression.Interactions 的引用。
        
//
        
// 文档将向您提供简单命令实现的示例,
        
// 您可以使用该示例,而不是使用 ActionCommand 并引用 Interactions 程序集。
        
//
        
//this.MyCommand = new ActionCommand(this.MyFunction);
    }

    
protected override void OnAttached()
    {
        
base.OnAttached();

        
// 插入要在将 Behavior 附加到对象时运行的代码。
    }

    
protected override void OnDetaching()
    {
        
base.OnDetaching();

        
// 插入要在从对象中删除 Behavior 时运行的代码。
    }

    
/*
    public ICommand MyCommand
    {
        get;
        private set;
    }
     
    private void MyFunction()
    {
        // 插入要在从对象中删除 Behavior 时运行的代码。
    }
    
*/
}

 

  要实现自定义行为通过此行为模板进行自我扩展就行了,位于System.Windows.Interactivity中的Behavior提供了将行为或命令进行封装以达到可进行附加到其他的一个对象上,需要注意的是自定义行为默认继承Behavior<DependencyObject>,使用DependencyObject类型的行为是不能访问对象的鼠标事件的,如果要访问鼠标操作的事件,可以使用具体的UI组件类型或者直接使用UI元素基类UIElement。

 

  下面为将本篇前面实现对象拖放功能的代码进行了行为的封装,完整代码如下:

/// <summary>
/// Behavior:封装行为和命令,便于附加到对象中。
/// DependencyObject:不能实现访问鼠操作事件
/// UIElement:可访问鼠标事件
/// </summary>
public class DragBehavior : Behavior<UIElement>
{
    
private UIElement attachedElement;
    
private UserControl parent;
    
private bool IsMouseCaptured;
    
private Point MousePosition;

    
protected override void OnAttached()
    {
        attachedElement 
= this.AssociatedObject;
        parent 
= Application.Current.RootVisual as UserControl;
        attachedElement.MouseLeftButtonDown 
+= (s, e) => OnMouseLeftButtonDown(s, e);
        attachedElement.MouseLeftButtonUp 
+= (s, e) => OnMouseLeftButtonUp(s, e);
        attachedElement.MouseMove 
+= (s, e) => OnMouseMove(s, e);
    }

    
private void OnMouseMove(object sender, MouseEventArgs e)
    {
        FrameworkElement element 
= sender as FrameworkElement;
        
if (IsMouseCaptured)
        {
            
double Y = e.GetPosition(null).Y - MousePosition.Y;
            
double X = e.GetPosition(null).X - MousePosition.X;

            X 
= X + (double)element.GetValue(Canvas.LeftProperty);
            Y 
= Y + (double)element.GetValue(Canvas.TopProperty);

            element.SetValue(Canvas.LeftProperty, X);
            element.SetValue(Canvas.TopProperty, Y);

            MousePosition 
= e.GetPosition(null);
        }
    }

    
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element 
= sender as FrameworkElement;
        IsMouseCaptured 
= false;
        element.ReleaseMouseCapture();
        MousePosition.X 
= MousePosition.Y = 0;
        element.Cursor 
= null;
    }

    
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element 
= sender as FrameworkElement;
        MousePosition 
= e.GetPosition(null);
        IsMouseCaptured 
= true;
        element.CaptureMouse();
        element.Cursor 
= Cursors.Hand;
    }

    
protected override void OnDetaching()
    {
        
base.OnDetaching();
    }
}

 

  通过行为特性将对象的拖放功能进行封装以达到复用的目的,以上就全部实现了这个功能,测试可通过Ctrol+Shift+B编译项目,然后通过“资产”面板就可以发现以上自定义扩展的拖放行为。

        

 

  使用行为非常简单,打开Blend的资源面板中,选中需要使用的行为,将其拖放到要使用该行为的对象(Blend中设计的界面对象)上就行了。其实在Blend也提供了拖放行为:MouseDragElementBehavior,直接使用这个行为和本篇所介绍的实现达到的是同样的效果。以下为分别使用这两种行为所对应生成的XAML编码:

 

<UserControl
    
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i
="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:local
="clr-namespace:DragBehavior"
    xmlns:il
="clr-namespace:Microsoft.Expression.Interactivity.Layout;assembly=Microsoft.Expression.Interactions"
    x:Class
="DragBehavior.MainControl"
    Width
="800" Height="600">
    
<Canvas x:Name="LayoutRoot" Background="White">
        
<Rectangle Fill="#FFFF0000" Stroke="#FF000000" Height="100" Width="100" Canvas.Left="100" Canvas.Top="100">
            
<i:Interaction.Behaviors>
                
<il:MouseDragElementBehavior/>
            
</i:Interaction.Behaviors>
        
</Rectangle>
        
<Ellipse Fill="#FF0000FF" Stroke="#FF000000" Height="100" Width="100" Canvas.Top="219" Canvas.Left="397">
            
<i:Interaction.Behaviors>
                
<local:DragBehavior/>
            
</i:Interaction.Behaviors>
        
</Ellipse>
    
</Canvas>
</UserControl>

 

 

  推荐资源:

  Expression Blend实例中文教程(9) - 行为快速入门Behaviors

  Silverlight中实现强壮的、可复用的拖放行为 

  Silverlight & Blend动画设计系列文章

  MSDN:http://msdn.microsoft.com/zh-cn/library/cc189090(VS.95).aspx

  http://www.silverlight.net/learn/quickstarts/animations/

 

版权说明

  本文属原创文章,欢迎转载且注明文章出处,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

posted on 2018-10-21 13:36 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/9824761.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450950.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql查询显示行号

见&#xff1a;http://blog.csdn.net/muzizhuben/article/details/49449853 使用mysql查询显示行号&#xff0c;没有像oracle这么方便。 不过也可以通过设定变量显示行号&#xff0c;例如&#xff1a; -- 生成 行号 select r:r1 as rowno , a.* from my_tb a ,(select r:0) b …

scanf 用法大全

关于标准库函数scanf论坛上很多人对scanf的不太了解&#xff0c;导致程序出错&#xff0c;我想把scanf的具体用法贴出来&#xff0c;希望大家可以共同进步&#xff0c;有什么不对的地方可以提出来。int scanf(char *format&#xff0c;...);这应该是scanf的标准形式。先说说关于…

深入了解Spring IoC

IoC全称Inversion of Control即控制反转&#xff0c;它还有一个别名依赖注入。spring利用Ioc容器帮我们自动构建对象及注入依赖对象&#xff0c;减少了对象构建与业务代码的耦合&#xff0c;使得我们能够更加高效愉快的写bug&#x1f41e;了(&#xffe3;▽&#xffe3;)"…

软文营销实战记录

最近拜读了徐茂权老师的《 网络营销决胜武器(第2版)》&#xff0c;下面会梳理书中的内容&#xff0c;记录下以后可能会用到的软文营销的技巧。 一、软文载体 1、平面媒体软文&#xff1a;报纸、期刊。 2、非正式出版的基于印刷、打印形式载体的软文&#xff1a;企业印刷的宣传册…

oracle中rownum和row_number()的区别

见&#xff1a;http://www.jb51.net/article/65960.htm row_number()over(partition by col1 order by col2)表示根据col1分组&#xff0c;在分组内部根据col2排序&#xff0c;而此函数计算的值就表示每组内部排序后的顺序编号&#xff08;组内连续的唯一的&#xff09;。 与ro…

java类加载顺序

在java中类的加载、初始化都是在程序运行期完成的&#xff0c;虽然会稍微增加开销&#xff0c;但是却很大的增加了灵活性&#xff0c;我们可用在运行期间动态的去网络或其他地方加载一个二进制流来作为程序代码的一部分。接下来我们简单介绍下java类加载过程。 从上图中我们可…

dealloc不调用的情况

2019独角兽企业重金招聘Python工程师标准>>> 1、没有停止定时器 - (void)dealloc { [_timer invalidate]; _timer nil; } 2、VC中有代理Delegate&#xff0c;需要设置delegate的时候&#xff0c;设置为weak property (nonatomic,weak) id<ZoeEatDe…

day10-列表生成式

列表生成式即List Comprehensions&#xff0c;是Python内置的非常简单却强大的可以用来创建list的生成式。 1、生成一个列表 a [i for i in range(1,100) if i%21]print(list(a))或print(a)[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, …

jrebel、JavaRebel

见&#xff1a;https://baike.baidu.com/item/jrebel/1115725?fraladdin JRebel是一套JavaEE开发工具。中文名jrebel属 性JavaEE开发工具资 费收费软件作 用Jrebel 可快速实现热部署JRebel是一套JavaEE开发工具。JRebel允许开发团队在有限的时间内完成更多的任务修正…

自己写函数库

大家现在写 程序&#xff0c;是不是都是用新唐提供的函数库&#xff1f;在体验 开发板的一开始&#xff0c;我也是使用函数库&#xff0c;毕竟这个太方便了。可是有一天&#xff0c;我发现一个只使用时钟和IO以及 调试 串口的程序居然查过了16k的时候&#xff0c;我震惊了&…

[MicroPython]stm32f407控制DS18B20检测温度

2019独角兽企业重金招聘Python工程师标准>>> 1.实验目的 1. 学习在PC机系统中扩展简单I/O 接口的方法。 2. 进一步学习编制数据输出程序的设计方法。 3. 学习DS18B20的接线方法&#xff0c;并利用DS18B20检测当前温度。 2.所需元器件 F407Micropython开发板…

带你理解Spring AOP

AOP概述 在我们的日常开发中&#xff0c;除了正常业务逻辑外&#xff0c;还可能经常会需要在业务逻辑的特定位置加入日志&#xff0c;以便于调试和问题分析。但是这种插入日志的逻辑和业务逻辑间并不存在连续性和依赖性&#xff0c;这种逻辑侵入随着项目的不断发展&#xff0c…

10.20随笔

ES6 ECMAScript是一种由Ecma国际&#xff08;前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association&#xff09;通过ECMA-262标准化的脚本程序设计语言。 这种语言在万维网上应用广泛&#xff0c;它往往被称为JavaScript或JScript&#xff0c;但…

极客招募令!兄弟杯区块链极客竞技大赛在上海等您来战!

据悉&#xff0c;由国内首家区块链技术社区区块链兄弟主办&#xff0c;旺链科技、离子链、中国云体系产业创新战略联盟、无退社区、指旺金科等单位强力支持&#xff0c;HiBlock区块链社区、火球财经、布洛克财经、海豚区块链、区块网等百家技术社区和媒体通力合作的兄弟杯区块链…

Java中Web程序修改配置文件不重启服务器的方法

见&#xff1a;http://blog.sina.com.cn/s/blog_69398ed9010191jg.html 另&#xff1a;http://ekisstherain.iteye.com/blog/1701463 jrebel 、JavaRebel是什么&#xff0c;见另一博客&#xff1a;jrebel/JavaRebel 开发环境 1. JDK 2. MyEclipse 3. Tomcat 4. Struts2 5.…

ffmpeg-0.6.3 移植到 windows 开源代码

ffmpeg-0.6.3开源编码解码库&#xff0c;从linux下移植到windows vs2005&#xff0c;全部开源。 需要 Intel C Compile 和 开源的SDL库支持&#xff0c;由于 Intel C Compile支持C99语法&#xff0c;所以源代码改动很小很小。 主要的修改 1&#xff1a;添加了linux中有而wind…

一起唠唠分布式锁

&#xff08;1&#xff09;分布式锁和分布式事务的区别 1.分布式锁是在集群环境下&#xff0c;用来控制不同机器对全局共享资源的访问。 2.分布式事务是在集群环境下&#xff0c;用来保证全局事务的一致性&#xff0c;保证多个数据库的数据整体上能正确的从一个一致性状态转到…

luogu2577/bzoj1899 午餐 (贪心+dp)

首先&#xff0c;应该尽量让吃饭慢的排在前面&#xff0c;先按这个排个序 然后再来决定每个人到底去哪边 设f[i][j]是做到了第i个人&#xff0c;然后1号窗口目前的总排队时间是j&#xff0c;目前的最大总时间 有这个i和j的话&#xff0c;再预处理出前i个人的排队总时间sum[i]&a…

wpf中xps文档合并功能实现

原文:wpf中xps文档合并功能实现跟着上一篇的xps文档套打的文章&#xff0c;近期一直在研究xps打印技术&#xff0c;其中用户提到了一个需求&#xff0c;要求能够多页面进行打印&#xff0c;我的想法是&#xff0c;先生成xps文件&#xff0c;然后将文件读取出来以后&#xff0c;…

DCT(离散余弦变换(DiscreteCosineTransform))

离散余弦变换&#xff08;Discrete Cosine Transform&#xff0c;简称DCT变换&#xff09;是一种与傅立叶变换紧密相关的数学运算。在傅立叶级数展开式中&#xff0c;如果被展开的函数是实偶函数&#xff0c;那么其傅立叶级数中只包含余弦项&#xff0c;再将其离散化可导出余弦…