原文: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. [LeetCode]题解(python):048-Rotate Image

    题目来源 https://leetcode.com/problems/rotate-image/ You are given an n x n 2D matrix representing an im ...

  2. leetcode:Factorial Trailing Zeroes

    Given an integer n, return the number of trailing zeroes in n!. 最初的代码 class Solution { public: int t ...

  3. jquery效果

    //隐藏显示 <!doctype html> <html lang="en"> <head> <meta charset="UT ...

  4. SDUT2165:Crack Mathmen(快速幂)

    题目:http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2165&cid=1431 快速幂. #include <iostream> ...

  5. Siri开源了,33%的开发者持疑虑态度,你呢?

    33%的中国开发者对Siri 开放持疑虑态度? 目前来说在iOS 10中,Siri API仅仅支持六类应用程序:打车,通讯,照片搜索,支付,网络电话和锻炼.另外还有一个面向汽车制造商的特殊使用案例,让 ...

  6. Visual Studio 中 UNICODE 宏的设置

    项目属性-> 配置属性 -> 常规 -> 字符集 (多字节字符集即没有设置UNICODE宏, 使用Unicode字符集就是设置了UNICODE宏) 设置的效果可以去 C/C++ -& ...

  7. iOS 黑屏

    1. 首先看操作系统是否有很多Bug 9.0.2 的系统不稳定. http://tech.163.com/15/1020/05/B6BL6PML000915BD.html

  8. python 归档tarfile,zipfile学习

    一.tarfile 用法: tarfile.open(cls, name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)  返回一个Tar ...

  9. 学习OpenCV——Kalman滤波

    背景: 卡尔曼滤波是一种高效率的递归滤波器(自回归滤波器), 它能够从一系列的不完全及包含噪声的测量中,估计动态系统的状态.卡尔曼滤波的一个典型实例是从一组有限的,包含噪声的,对物体位置的观察序列(可 ...

  10. leetcode96 Unique Binary Search Trees

    题目: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For e ...