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 ...
随机推荐
- UML静态类图
0,主要分为类.接口.协作.关系,这四种元素.作用:a,显示类.接口以及他们之间的静态结构和关系:b,用于描述系统的结构化设计. 1,类 CStudent +m_strName : string +S ...
- HTML5之拖放
- Draggable 标签 文件拖放 99年IE5开始,05后所有浏览器支持(除了opera) <li id=be draggable=true ondragstart="star ...
- MySQL的 inner join on 与 left join on
WHERE子句中使用的连接语句,在数据库语言中,被称为隐性连接.INNER JOIN……ON子句产生的连接称为显性连接. inner join:理解为“有效连接”,两张表中都有的数据才会显示left ...
- 实验一:点亮led
一.先看原理图:
- grails导入excel
grails导入excel,意思是说从excel表中读取多条数据,批量写入数据库. 有2种方案,1是使用grails的excel插件,2是调用java代码使用POI等第三方java控件. 今天比较累, ...
- 《Visual C++ 程序设计》读书笔记 ----第8章 指针和引用
1.&取地址:*取内容. 2.指针变量“++”“--”,并不是指针变量的值加1或减1,而是使指针变量指向下一个或者上一个元素. 3.指针运算符*与&的优先级相同,左结合:++,--,* ...
- 由底层和逻辑说开去--c++之引用的深入剖析
在学c++的时候 我遇到的第一个问题就是这个引用,引用是什么东西,我的c++启蒙教科书是c++ primer plus,这本书上说的是:引用是已定义变量的别名,可以使用这个引用来表示这个变量:每当看到 ...
- 2014年辛星完全解读Javascript第五节 break和continue与错误处理
先说一下break和continue的主要用法吧,break用于跳出循环,continue用于跳过该循环中的一个迭代.简单的说,就是break直接从该语句跳出,但是continue不会跳出该循环语句, ...
- [Learn Android Studio 汉化教程]第二章:Android Studio概述(一)
[Learn Android Studio ]第二章:Android Studio概述(一) Android Studio是一个视窗化的开发环境.为了充分利用有限的屏幕空间,不让你束手束脚,Andro ...
- 使用NPIO操作Excel
using System; using System.Collections.Generic; using System.Linq; using System.Text; using NPOI.SS. ...