【WPF学习】第三十八章 行为
2021-03-20 14:25
标签:定位 时间 功能 ted protected 客户 程序设计 fill eric 样式提供了重用一组属性设置的实用方法。它们为帮助构建一致的、组织良好的界面迈出了重要的第一步——但是它们也是有许多限制。 问题是在典型的应用程序中,属性设置仅是用户界面基础结构的一小部分。甚至最基本的程序通常也需要大量的用户界面代码,这些代码与应用程序的功能无关。在许多程序中,用于用户界面任务的代码(如驱动动画、实现平滑效果、维护用户界面状态,以及支持诸如拖放、缩放以及停靠等用户界面特性)无论是在数量山还是复杂性上都超出了业务代码。许多这类代码是通用的,这意味着在创建的每个WPF对象中需要编写相同的内容。所有这些工作几乎都单调乏味的。 为回应这一挑战,Expression Blend创作者开发了称为行为(behavior)的特征。其思想很简单:创建封装了一些通用用户界面功能的行为。这一功能可以是基本功能(如启动故事板或导航到超链接),也可以是复杂功能(如处理多点触摸交互,或构建使用实时物理引擎的碰撞模型)。一旦构建功能,就可将它们添加到任意应用程序的另一个控件中,具体方法是将该控件链接到适当的行为并设置行为的属性。在Expression Blend中,只通过拖放操作就可以使用行为。 一、获取行为支持 重用用户界面的代码通用块得基础结构不是WPF的一部分。反而,它被捆绑到Expression Blend。这是因为行为开始时作为Expression Blend的设计时特性引入的。但这并不意味着行为只能用于Expression Blend。只需要付出很少的努就可以在Visual Studio应用程序中的创建和使用行为。只需要手动缩写标记,而不是使用工具箱。 为了获得支持行为的程序集,有两种选择: 无论是使用Expression Blend的哪个版本,都可以在文件夹中看到所需的两个相同的重要程序集: 二、理解行为模型 行为特性具有两个版本:一个版本是旨在Silverlight添加行为支持,Silverlight是Microsoft的针对浏览器的富客户端插件;而另一个版本是针对WPF设计的。尽管这两个版本提供了相同的特性,但行为特性和Silverlight领域更吻合,因为它弥补了更大的鸿沟。与WPF不同,Silverlight不支持触发器,所以实现行为的程序集也实现触发器更合理。然而,WPF支持触发器,行为特性包含自己的触发器系统,而触发器系统与WPF模型不匹配,这确实令人感到有些困惑。 问题在于具有类似名称的这两个特性有部分重合但不完全相同。在WPF中,触发器最重要的角色是构建灵活的样式和控件模板。在触发器的帮助下,样式和模板变得更加智能;例如,当一些熟悉发生变化时可应用可视化效果。然而,Expression Blend中的触发器系统具有不同的目的。通过使用可视化设计工具,允许为应用程序添加简单功能。换句话说,WPF触发器支持更加强大的样式和控件模板。而Expression Blend触发器支持快速的不需要代码的应用程序设计。 那么,对于使用WPF的普遍开发人员来说所有这些意味着什么呢?下面是几条指导原则: 三、创建行为 行为旨在封装一些UI功能,从而可以不比编写代码就能够将其应用到元素上。从另一个角度看,每个行为都为元素提供了一个服务。该服务通常涉及监听几个不同的事件并执行几个相关的操作。 为更好地理解行为,最好自己创建一个行为。设想希望为任意元素提供使用鼠标在Canvas面板上拖动元素的功能。对于单个元素实现该功能的基本步骤是非常简单的——代码监听鼠标事件并修改设置相应Canvas坐标的附加属性。但通过付出更多一点的努力,可将该代码转换为可重用的行为,该行为可为Canvas面板上的所有元素提供拖动支持。 在继续之前,创建一个WPF类库程序集。在该程序集中,添加System.Windows.Interactivity.dll程序集的引用。然后,创建一个继承自Behavior基类的类。Behavior是通用类,该类使用一个类型参数。可使用该类型参数将行为限制到特定的元素,或使用UIElement或FrameworkElement将它们都包含进来。如下所示: 在任何行为中,第一步要覆盖OnAttached()和OnDetaching()方法。当调用OnAttached()方法时,可通过AssociatedObject属性访问放置行为的元素,并可关联事件处理程序。当调用OnDetaching()方法时,移除事件处理程序。 下面是DragInCanvasBehavior类用于监视MouseLeftButtonDown、MouseMove以及MouseLeftButtonUp事件代码: 最后一步是在事件处理程序中运行适当的代码。例如,当用户单击鼠标左键时,DragInCanvasBehavior开始拖动操作、记录元素左上角与鼠标指针之间的偏移并捕获鼠标: 当元素处于拖动模式并移动鼠标时,重新定位元素: 当释放鼠标键时,结束拖动: DragInCanvasBehavior类的完整代码如下所示: 四、使用行为 为测试行为,创建一个新的WPF应用程序项目。然后添加对定义DragInCanvasBehavior类的类库以及System.Windows.Interactivity.dll程序集得应用。接下来在XML中映射这两个标记名称。假定存储DragInCanvasBehavior类的类库名为CustomBehaviorsLibrary,所需的标记如下所示: 为使用该行为,只需要使用Interaction.Behaviors附加属性在Canvas面板中添加任意元素。下面的标记创建一个具有三个图形的Canvas面板。两个Ellipse元素使用了DragInCanvasBehavior,并能在Canvas面板中拖动。Rectangle元素没有使用DraginCanvasBehavior,因此无法移动。 下图显示了该例的运行效果。 但这并非是全部内容。如果正在使用Expression Blend进行开发,行为甚至提供了更好的设计体验——可以根本不用编写任何标记。 【WPF学习】第三十八章 行为 标签:定位 时间 功能 ted protected 客户 程序设计 fill eric 原文地址:https://www.cnblogs.com/Peter-Luo/p/12299855.html
public class DragInCanvasBehavior : Behavior
protected override void OnAttached()
{
base.OnAttached();
// Hook up event handlers.
this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
this.AssociatedObject.MouseMove += AssociatedObject_MouseMove;
this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
}
protected override void OnDetaching()
{
base.OnDetaching();
// Detach event handlers.
this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
this.AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;
}
private Canvas canvas;
// Keep track of when the element is being dragged.
private bool isDragging = false;
// When the element is clicked, record the exact position
// where the click is made.
private Point mouseOffset;
private void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Find the canvas.
if (canvas == null) canvas = VisualTreeHelper.GetParent(this.AssociatedObject) as Canvas;
// Dragging mode begins.
isDragging = true;
// Get the position of the click relative to the element
// (so the top-left corner of the element is (0,0).
mouseOffset = e.GetPosition(AssociatedObject);
// Capture the mouse. This way you‘ll keep receiveing
// the MouseMove event even if the user jerks the mouse
// off the element.
AssociatedObject.CaptureMouse();
}
private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
// Get the position of the element relative to the Canvas.
Point point = e.GetPosition(canvas);
// Move the element.
AssociatedObject.SetValue(Canvas.TopProperty, point.Y - mouseOffset.Y);
AssociatedObject.SetValue(Canvas.LeftProperty, point.X - mouseOffset.X);
}
}
private void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
AssociatedObject.ReleaseMouseCapture();
isDragging = false;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
namespace CustomBehaviorsLibrary
{
public class DragInCanvasBehavior : Behavior
Window x:Class="BehaviorTest.DragInCanvasTest"
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:custom="clr-namespace:CustomBehaviorsLibrary;assembly=CustomBehaviorsLibrary"
Title="DragInCanvasTest" Height="300" Width="300">
Canvas>
Rectangle Canvas.Left="10" Canvas.Top="10" Fill="Yellow" Width="40" Height="60">Rectangle>
Ellipse Canvas.Left="10" Canvas.Top="70" Fill="Blue" Width="80" Height="60">
i:Interaction.Behaviors>
custom:DragInCanvasBehavior>custom:DragInCanvasBehavior>
i:Interaction.Behaviors>
Ellipse>
Ellipse Canvas.Left="80" Canvas.Top="70" Fill="OrangeRed" Width="40" Height="70">
i:Interaction.Behaviors>
custom:DragInCanvasBehavior>custom:DragInCanvasBehavior>
i:Interaction.Behaviors>
Ellipse>
Canvas>
DragInCanvasTest完整代码:
Window x:Class="BehaviorTest.DragInCanvasTest"
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:custom="clr-namespace:CustomBehaviorsLibrary;assembly=CustomBehaviorsLibrary"
Title="DragInCanvasTest" Height="300" Width="300">
Canvas>
Rectangle Canvas.Left="10" Canvas.Top="10" Fill="Yellow" Width="40" Height="60">Rectangle>
Ellipse Canvas.Left="10" Canvas.Top="70" Fill="Blue" Width="80" Height="60">
i:Interaction.Behaviors>
custom:DragInCanvasBehavior>custom:DragInCanvasBehavior>
i:Interaction.Behaviors>
Ellipse>
Ellipse Canvas.Left="80" Canvas.Top="70" Fill="OrangeRed" Width="40" Height="70">
i:Interaction.Behaviors>
custom:DragInCanvasBehavior>custom:DragInCanvasBehavior>
i:Interaction.Behaviors>
Ellipse>
Canvas>
Window>
下一篇:C# 泛型委托和多播委托