WPF之Behavior
本文主要是以实现拖动元素作为例子。
创建Behavior:
通常这个类会继承自Behavior<T>,其中T就是此Behavior服务的对象,在此处使用的是UIElement,也就是虽有的UIElement类型的元素都可以使用。
public class DragInCanvasBehavior : Behavior<UIElement>
{
//元素父节点
private Canvas canvas;
//标识是否进入拖动
private bool isDraging = false;
//按下鼠标时的坐标(用于计算要移动的位置)
private Point mouseOffset; /// <summary>
/// 附加行为后
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
//添加鼠标事件(AssociatedObject也就是当前应用此Behavior的元素)
this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
this.AssociatedObject.MouseMove += AssociatedObject_MouseMove;
this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
} void AssociatedObject_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//释放拖动状态
isDraging = false;
} void AssociatedObject_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
//如果进入拖动状态
if (isDraging)
{
//得到新的位置
Point newPoint = e.GetPosition(canvas);
//旧的坐标加上新坐标和旧坐标的差
mouseOffset.X += newPoint.X - mouseOffset.X;
mouseOffset.Y += newPoint.Y - mouseOffset.Y; //设置元素的Left和Top,之所以要用X(Y)减去Width(Height),主要是为了使鼠标在元素中心
Canvas.SetLeft(this.AssociatedObject, mouseOffset.X-(this.AssociatedObject as FrameworkElement).ActualWidth/);
Canvas.SetTop(this.AssociatedObject, mouseOffset.Y - (this.AssociatedObject as FrameworkElement).ActualHeight/);
}
} void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//将元素的父节点元素赋值为Canvas(之所以使用Canvas,是因为Canvas容易动态布局)
if (canvas == null)
canvas = (Canvas)VisualTreeHelper.GetParent(this.AssociatedObject);
//进入拖动状态
isDraging = true;
//获得初始位置
mouseOffset = e.GetPosition(this.AssociatedObject);
this.AssociatedObject.CaptureMouse();
} /// <summary>
/// 分离行为
/// </summary>
protected override void OnDetaching()
{
//移除鼠标事件
this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
this.AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;
}
}
在WPF中实现拖动,一般只需三个事件即可,MouseLeftButtonDown、MouseLeftButtonUp、MouseMove。Down事件负责进入拖动状态,并且记录初始的鼠标坐标(用于拖动中动态修改元素的位置),同时也要得到当前元素的Parent即Canvas,这样才可以在Move时候获得相对于Canvas的新坐标;Up事件负责状态变为正常,这时候在移动就没变化的;Move事件负责的事情比较重要,得到当前鼠标相对于Canvas的新坐标,然后和旧坐标进行计算,最后设置元素的新坐标。
使用Behavior:
注:如果你还没有引用Microsoft.Expression.Interactions.dll和System.Windows.Interactivity.dll,那么赶紧引用进来吧(如果你么有安装Blend,那么就点击下载吧)。
<Window x:Class="WpfApplication2.MainWindow"
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:behavior="clr-namespace:CustomBehaviorsLibrary;assembly=CustomBehaviorsLibrary"
Title="MainWindow" Height="350" Width="525">
<Canvas Background="LightBlue">
<Rectangle Height="50" Width="50" Fill="Green" >
<i:Interaction.Behaviors>
<behavior:DragInCanvasBehavior></behavior:DragInCanvasBehavior>
</i:Interaction.Behaviors>
</Rectangle>
</Canvas>
</Window>
添加对Interactivity和Behavior所属程序及的引用,页面内容很简单,一个Canvas包含一个Rectangle,在Rectangle中设置Behaviros为创建的Behavior,这样神奇的事情就发生了,运行程序,拖动Rectangle,就可以看到可以改变位置了哦。
注:由于本文的示例Behavior和WPF应用程序是分离的,所以在此需要添加对Behavior所在类库的引用,同时在Window标签中添加对Behavior所属Assembly的引用,如果你的Behavior和XAML在同一个程序集,则可以进行适当的修改。
XAML中Trigger和Action组合之后应该是等同于一个Behavior,可以参见本人另一篇日志(Silverlight之Styles和Behaviors)。
希望大家多提意见和建议,如果评论,我会在第一时间回复。
WPF之Behavior的更多相关文章
- 【WPF】 Behavior
Hello,Behavior 引言 在看PDC-09大会的视频时,其中一篇讲利用Blend来扩展Silverlight元素的行 为,当时感觉很酷:在Blend中,将MouseDra ...
- 【WPF】Behavior的使用
如何将一个行为附加到某个元素上呢?我们可以通过自定义一个Behavior! 我们首先看一下IAttachedObject接口,Behavior默认继承之这个接口 // 摘要: // 供可以附加到另一个 ...
- wpf.xaml.behavior
Install-Package Microsoft.Xaml.Behaviors.Wpf Remove reference to “Microsoft.Expression.Interactions” ...
- WPF TextBox PreviewTextInput handle IME (chinese)
今天调试自己写的WPF的Behavior, 是关于TextBox只能输入数据或者小数点的. 发现有个问题, 就是英文IME下字母等等都能过滤, 但是一旦切换到中文输入法, 就会发现在OnPreview ...
- WPF点滴(3) 行为-Behavior
为了定制个性化的用户界面,我们通常会借助于WPF强大的样式(style),修改控件属性,重写控件模板(template),样式帮助我们构建一致的个性化控件.通过样式可以调整界面的显示效果,这只是界面构 ...
- WPF自定义行为Behavior,实现双击控件复制文本
WPF引用xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity& ...
- WPF Interaction框架简介(一)——Behavior
在WPF 4.0中,引入了一个比较实用的库——Interactions,这个库主要是通过附加属性来对UI控件注入一些新的功能,除了内置了一系列比较好用的功能外,还提供了比较良好的扩展接口.本文这里简单 ...
- WPF教程十:如何使用Style和Behavior在WPF中规范视觉样式
在使用WPF编写客户端代码时,我们会在VM下解耦业务逻辑,而剩下与功能无关的内容比如动画.视觉效果,布局切换等等在数量和复杂性上都超过了业务代码.而如何更好的简化这些编码,WPF设计人员使用了Styl ...
- [No0000124]WPF 扩展控件Behavior的几种方式
一.使用Attached Dependency Property的方式 (1)定义Attached Dependency Property public static class DigitsOnly ...
随机推荐
- [转]Nuget挂了的解决方法
今天用Nuget下一个程序包时,发现Nuget挂了:未能解析此远程名称:'nuget.org'.第一反应就是方校长抖威风了,挂个代理上 http://nuget.org 试了下,果然好好的. 用命令n ...
- Java使用基本JDK操作ZIP文件以及zip文件的加密、解密等功能
Java使用基本JDK操作ZIP文件 http://blog.csdn.net/zhyh1986/article/details/7723649 Java解压和压缩带密码的zip文件 http://b ...
- System.UnauthorizedAccessException: 拒绝访问 temp 目录。用来运行 XmlSerializer 的标识“NT AUTHORITY\NETWORK SERVICE”没有访问 temp 目录的足够权限。CodeDom 将使用进程正在使用的用户帐户进行编译,这样,如
解决方案:IIS的应用程序池权限不够,应用程序给localsystem账号权限即可. 以客户的服务器系统2003sp2为例,修改步骤如下: 控制面板---管理工具--Internet 信息服务(IIS ...
- python(六)面向对象
1.封装 支持多重继承,但如果不需要的时候最好不要使用,避免出现不必要的bug: 2.继承 3.多态 4.构造函数 5.私有和共有 在属性前写两个下滑线定义就是私有的
- aix 安装redis
下载最新rpm安装包 http://www.perzl.org/aix/index.php?n=Main.Redis # uname -aAIX rhjf 1 6 00C5CC964C00# pwd/ ...
- PHP获取搜索引擎关键字来源(百度、谷歌、雅虎、搜狗、搜搜、必应、有道)
<?php //获取来自搜索引擎入站时的关键词 function get_keyword($url,$kw_start) { $start=stripos($url,$kw_start); $u ...
- Spark Streaming揭秘 Day10 从BlockGenerator看接收数据的生命周期
Spark Streaming揭秘 Day10 从BlockGenerator看接收数据的生命周期 昨天主要介绍了SparkStreaming中对于Receiver的生命周期管理,下面让我们进入到Re ...
- Oracle 监听动态注册与静态注册
静态注册 静态注册是在启动listener时,listener会从listener.ora文件中获取服务名及相关信息.信息包括:实例名和服务名等. --静态注册时,listener.ora中的内容如下 ...
- WPF 多线程处理(2)
WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) WPF UI 设计需要自动适应窗体大小,那么 ...
- 数据库 mysql 优化器原理
MySQL查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行. 你的最终目标是提交SELECT语句查找数据行,而不是排除数据行.优化器试图排除数据 ...