原文:http://www.bjoernrochel.de/2009/08/19/the-attached-behavior-pattern/

The Attached Behavior Pattern

AUG 19TH, 2009

With new technologies often completely new patterns emerge as people try to check-out how far a technology might take them. One interesting example for this is the Attached Behavior Pattern which seems to get a lot of attention in the WPF and Silverlight community lately. It’s a great example of what you can do with those technologies that was previously only very hard to achieve (although sometimes in my calm moments it feels a little bit like a hack to me).

Anyway, here is what the pattern actually does:

The Attached Behavior Pattern uses the moment when an attached DependencyProperty is attached to a DependencyObject in order to wire event handlers to it. With this you’re able to extend the behavior of elements in the WPF trees with arbitrary code.

Let’s take a look at how this can be achieved. First of all we need a class deriving from DependencyObject in order to be able to provide an attached DependencyProperty. It uses the standard pattern of registering the IsEnabled DependencyProperty in the static constructor (which is a bit clunky, btw).

A behavior must derive from DependencyObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyBehavior : DependencyObject
{
public static readonly DependencyProperty IsEnabledProperty;
static MyBehavior ()
{
IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled", //Name of the property
typeof(bool),//Type of the attached property
typeof(MyBehavior),//Type of the class that provides the property
new FrameworkPropertyMetadata(false)); //Default value
}
public bool IsEnabled
{
get { return this.GetValue<bool>(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
}

Pretty standard stuff so far. However you can use another constructor of FrameworkPropertyMetdata in order to supply a callback which is called when the value of the attached property changes.

Registering for change notifications

1
2
3
4
5
IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled", //Name of the property
typeof(bool),//Type of the attached property
typeof(MyBehavior),//Type of the class that provides the property
new FrameworkPropertyMetadata(false, OnBehaviorEnabled)); //Default value + Callback

Next thing we need to do is to configure this attached property on the DependencyObject we want to attach behavior to. This is preferably done in XAML. You’ve got at least two options for doing the configuration. The first option is to set your attached property in the XAML file of a UserControlPage or Window directly at the source, the element you want to attach behavior to.

Wiring it via XAML

1
<TextBox myNamespace:MyBehavior.IsEnabled="true" />

The other option is to use the the power of styles (an area were WPF really shines imho) in order to set it for all elements to which a style is applied.

Wiring it via XAML and styles

1
2
3
<Style TargetType="TextBox">
<Setter Property="myNamespace:MyBehavior.IsEnabled" Value="true" />
</Style>

Personally I very much vote for the second option, because it enables you to specify the attached behavior in a single place in contrast to configuring it at several places in your solution. Don’t repeat yourself, unless you really need to.

Now, fasten your seatbelts. This is were the fun begins. When the WPF / Silverlight infrastructure loads the compiled baml from the resources and builds the element tree from it (and with this attaches our new property to the specified elements) the callback method gets called.

Attaching to the target instance

1
2
3
4
5
6
7
8
9
10
11
12
private static void OnBehaviorEnabled(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
TextBox textBox = (TextBox)dependencyObject;
textBox.LostFocus += (s,e) =>
{
//Put your little piece of magic here
};
}

With first parameter of the callback you get a reference to the DependencyObject to which our attached property has been attached to. You’re now able to wire all sort of event handlers to the DependencyObject and are able to execute arbitrary code when the event occurs.

Here ends our journey for today. Attached Behaviors is a really nice technique which enabled me to do something that I always wanted to have in my WinForms apps but never found a satisfiing way to implement it (just a bit patience, I’m going to blog about it soon). I think it will be interesting to see how this pattern is used in the future. While new patterns always have the tendency to be overused, I think that this particular pattern can enable lots of valuable things …

【转】The Attached Behavior Pattern的更多相关文章

  1. 年度巨献-WPF项目开发过程中WPF小知识点汇总(原创+摘抄)

    WPF中Style的使用 Styel在英文中解释为”样式“,在Web开发中,css为层叠样式表,自从.net3.0推出WPF以来,WPF也有样式一说,通过设置样式,使其WPF控件外观更加美化同时减少了 ...

  2. 【WPF系列】基础学习-WPF设计模式概览

    引言 “设计模式”这个让程序员提起来就“酷”的东东,着实让让初学设计模式的programer自我陶醉一番.太多的经历,告诉我们“凡事都要个度,要学会适可而止”,否则过犹不及.“设计模式”也一样,切莫为 ...

  3. Yii源码阅读笔记(七)

    接上次的组件(component)代码: /** * Returns a list of behaviors that this component should behave as. * 定义该对象 ...

  4. Yii源码阅读笔记(六)

    组件(component),是Yii框架的基类,实现了属性.事件.行为三类功能,如果需要事件和行为的功能,需要继承该类,不需要可直接继承Object类: namespace yii\base; use ...

  5. wpf 面试题目

    初级工程师 解释什么是依赖属性,它和以前的属性有什么不同?为什么在WPF会使用它?什么是样式什么是模板绑定(Binding )的基础用法解释这几个类的作用及关系: Visual, UIElement, ...

  6. yii2源码学习笔记(四)

    继续了解组件Component.php /** * Returns a value indicating whether a property is defined for this componen ...

  7. yii2源码学习笔记(三)

    组件(component),是Yii框架的基类,实现了属性.事件.行为三类功能,如果需要事件和行为的功能,需要继承该类. yii\base\Component代码详解 <?php /** * @ ...

  8. Yii创建前台和后台登录表单和通过扩展 CWebUser 增加信息到 Yii::app()->user

    我参考了这篇文章来构建项目的前台和后台的目录结构.感谢Andy的这篇文章.按照所有的步骤,您将有单独的前台和后台面板,如: http://localhost/index.php // 前台 http: ...

  9. A WPF File ListView and ComboBox

    源码下载: Download FileListView_Version_2.zip Download FileListView_Version_2_Binaries.zip Download File ...

随机推荐

  1. ecshop

    if($cat_id == '205'){ $smarty->display('cat1.dwt', $cache_id); }elseif($cat_id == '2'){ $smarty-& ...

  2. 【转】Android性能优化之布局优化篇

     转自:http://blog.csdn.net/feiduclear_up/article/details/46670433 Android性能优化之布局优化篇 分类: andorid 开发2015 ...

  3. JDK的安装!力求简单明了!

    作为一个java语言的开发人员,第一件事就是安装JDK,就像当兵的要有刀枪,学生要有书本纸笔一样!话不多说,配置如下: 1.下载一个JDK安装包,解压到任意目录,我解压的是:C:\Tools\Java ...

  4. CSS:CSS定位和浮动

    CSS2.1规定了3种定位方案 1.Normal flow:普通流(相对定位 position relative.静态定位 position static) 普通流(normal flow,国内有人翻 ...

  5. PHP回调函数的几种用法

    PHP回调函数的实现方法 目录 前言      全局函数的回调      类静态函数的回调      对象的方法的回调      PHP事件模型(观察者模式)的实现思路    前言 最近在开发一个PH ...

  6. android中用Spannable在TextView中设置超链接、颜色、字体

    昨晚研读 ApiDemo 源码至 com.example.android.apis.text.Link 类.首先,看一下其运行效果:  要给 TextView 加上效果,方式主要有几种: 第一种,自动 ...

  7. Login failed知多少

    说起Login failed我们首先会想起密码错误,但密码错误只是众多login failed中的一个,本篇将罗列各类login failed在ERRORLOG中的表现,以及如何提取这类错误信息.通过 ...

  8. javascript设计模式学习之三—闭包和高阶函数

    一.闭包 闭包某种程度上就是函数的内部函数,可以引用外部函数的局部变量.当外部函数退出后,如果内部函数依旧能被访问到,那么内部函数所引用的外部函数的局部变量就也没有消失,该局部变量的生存周期就被延续. ...

  9. SQL 的简单命令(增删改查)

    数据库操作的资料: 链接: https://pan.baidu.com/s/1dFl3q6X 密码: nvy7-- 增:insert into 表名 (列名) values (值) ,'dew') - ...

  10. Spring Boot flyway的启动时机比较早

    flyway,如果已经创建的版本V1中已经更新,则会validation报错 at org.springframework.boot.devtools.restart.RestartLauncher. ...