`

zz - A base class for custom WPF binding markup extensions

    博客分类:
  • WPF
阅读更多

In author's original post, there is one article that describe a base class that you can extend to create some Custom Binding markup extension. 

 

Markup Extension is something like this in .xaml "{Binding Path=Name, Converter={StaticResource ResourceKey";

 

 

Binding Extension provide a neat mean that you can use to set complex types (types which can represent by String, or number - actually number are represent in string)... 

 

 

the orginal post is "A base class for custom WPF binding markup extensions"

 

Already tried to extend the Binding or BindingBase classes in order to write your own custom bindings? And failed because BindingBase.ProvideValue is sealed? Me too…

The result is a MarkupExtension that works around the issue that you cannot properly extend the Binding class. Basically, it allows you to write binding expressions with the usual syntax without having to worry about the underlying plumbing. Here’s a sample binding that adds an additional LookupKey property:

<TextBox Name="txtZipCode"
         Text="{local:LookupExtension Path=ZipCode,
                                      Mode=TwoWay,
                                      UpdateSourceTrigger=PropertyChanged,
                                      LookupKey=F5}"
/>

 

Decorating the Binding class

As extending the Binding class did not work, I tried a different approach:

  • Create a class that extends MarkupExtension rather than BindingBase. This class provides all the properties that are needed for a binding expression (SourcePathConverter, …).
  • Based on defined binding properties, the extension class internally creates a regularBinding and associates it with the targeted dependency object.

I wanted it to look somehow like this (dummy code!):

public class MyCustomExtension : MarkupExtension
{
  public override object ProvideValue(IServiceProvider provider)
  {
    //we only use this extension on textboxes
    TextBox tb = GetTextBoxFromProvider(provider);

    //create a binding and associate it with the text box
    Binding binding = CreateBinding(this.Source, this.Path);
    tb.SetBinding(TextBox.TextProperty, binding);

    //return a valid value
    return ...;
  }
}

And guess what - that worked :)

The result is an abstract base class that provides pretty much everything you need to create your custom binding classes. The BindingDecoratorBase provides properties for all kinds of binding expressions (SourcePathConverter etc.) and handles binding creation and association with the targeted dependency object for you:

 image

Basically, the class maintains its own binding class and just forwards the binding statements. For example, here’s the declaration of the Path property:

[DefaultValue(null)]
public PropertyPath Path
{
  get { return binding.Path; }
  set { binding.Path = value; }
}
 

Custom Binding Sample

Here’s a simple sample: Let’s say we have a TextBox that displays the ZipCode property of a bound item. The XAML for this bound control looks like this:

<TextBox Name="txtZipCode"
         Text="{Binding Path=ZipCode}"
/>

However, we want to interfere with the binding in order to add some additional value. For this example, we’d like to register the bound control with some kind of handler class. We could also do this with an attached property, but this is more fun ;)

First, I created a custom extension called LookupExtension that derives fromBindingDecoratorBaseBindingDecoratorBase provides all binding properties out of the box, so the binding expression itself (Path=ZipCode) remains intact. The only thing I had to change in XAML was the extension name and add the custom property for my extension (LookupKey):

<TextBox Name="txtZipCode"
         Text="{local:LookupExtension Path=ZipCode,
                                      LookupKey=F5}"
/>

As LookupExtension derives from BindingDecoratorBase, it is ensured that in the end, the text box will be bound to the ZipCode property just like with the original regular binding expression.

Below is a first implementation which does not yet add any additional value. Therefore, this extension would behave exactly like the original binding - the ZipCode property of the bound data item is displayed, and updating the TextBox changes the bound property value:

public class LookupExtension : BindingDecoratorBase
{
  //A property that can be set in XAML
  public string LookupKey { get; set; }

  public override object ProvideValue(IServiceProvider provider)
  {
    //delegate binding creation etc. to the base class
    return base.ProvideValue(provider);
  }
}

So what’s left is adding some custom code to the extension. Below is the complete sample. Basically, the bound control (the text box of the sample) is determined by invokingTryGetTargetItems and then registered with an InputHandler. That’s it:

public class LookupExtension : BindingDecoratorBase
{
  //A property that can be set in XAML
  public string LookupKey { get; set; }

  public override object ProvideValue(IServiceProvider provider)
  {
    //delegate binding creation etc. to the base class
    object val = base.ProvideValue(provider);

    //try to get bound items for our custom work
    DependencyObject targetObject;
    DependencyProperty targetProperty;
    bool status = TryGetTargetItems(provider, out targetObject,
                                              out targetProperty);

    if (status)
    {
      //associate an input listener with the control
      InputHandler.RegisterHandler(targetObject, LookupKey);
    }

    return val;
  }
}

Note the status flag in the snippet above! ProvideValue is also invoked at design time (within Visual Studio). In this case, the provider parameter is null, so be careful to validate your parameters or you’ll end up with a broken designer.

 

Problem: Attribute syntax with resources

During the implementation of the sample, I came across an annoying issue: You cannot nest static or dynamic resources within a custom markup extension due to a framework bug. This means that if you wanted to set the Source property explicitly, you could not write it like this:

<TextBox Name="txtZipCode"
         Text="{local:LookupExtension Source={StaticResource MyAddress}
                                      Path=ZipCode,
                                      LookupKey=F5}"
/>

The above snippet does not compile due to a bug I described here. As a result, you have to fall back to property element syntax if you need to explicitly setting the Source property or other resources (e.g. Converter):

<TextBox Name="txtZipCode">
  <TextBox.Text>
    <local:LookupExtension Source="{StaticResource MyAddress}"
                           Path="ZipCode"
                           LookupKey="F5" />
  </TextBox.Text>
</TextBox>

 

Source Code / Sample

I’ve assembled a simple project that contains the BindingDecoratorBase class and the LookupExtension I used as a sample (VS 2008 project).

You can download it here: custom-bindings.zip

Markup Extension Sample

 

分享到:
评论

相关推荐

    WPF优秀项目及源码 wpfkb-a16225f82c48

    wpfkb-a16225f82c48WPF优秀项目及源码 wpfkb-a16225f82c48WPF优秀项目及源码 wpfkb-a16225f82c48WPF优秀项目及源码 wpfkb-a16225f82c48WPF优秀项目及源码 wpfkb-a16225f82c48WPF优秀项目及源码 wpfkb-a16225f82c48...

    gong-wpf-dragdrop, GongSolutions.WPF.DragDrop 库是WPF的拖动'n'拖放框架.zip

    gong-wpf-dragdrop, GongSolutions.WPF.DragDrop 库是WPF的拖动'n'拖放框架 简介GongSolutions.WPF.DragDrop 库是一个易于使用的拖拉'n'拖放框架。特性使用 MVVM: 拖放逻辑可以放在ViewModel中。 代码不需要放在in中...

    WPF Binding绑定 Command命令基础学习源码

    在WPF(Windows Presentation Foundation)开发中,数据绑定和命令是两个非常重要的概念,它们能够实现界面(View)与业务逻辑(ViewModel)之间的松耦合。让我们深入探讨这两个主题。 **WPF数据绑定(Binding)** ...

    wpf binding 的两种方法

    在Windows Presentation Foundation (WPF) 中,数据绑定是将用户界面元素与数据源连接的关键机制,使得UI元素的属性能够动态地反映数据源的变化。标题和描述提到了两种WPF数据绑定的方法,这里我们将深入探讨这两种...

    WPF21个优秀项目及源码 helixtoolkit-8c0d58aa0295

    WPF21个优秀项目及源码 helixtoolkit-8c0d58aa0295WPF21个优秀项目及源码 helixtoolkit-8c0d58aa0295WPF21个优秀项目及源码 helixtoolkit-8c0d58aa0295WPF21个优秀项目及源码 helixtoolkit-8c0d58aa0295WPF21个优秀...

    WPF Binding转换与校验

    ### WPF Binding转换与校验 #### 一、概述 WPF(Windows Presentation Foundation)作为Microsoft推出的用于构建桌面应用程序的框架之一,提供了丰富的特性和工具来帮助开发者构建高性能且美观的应用程序。其中,...

    WPF Binding

    其中,数据绑定(WPF Binding)是一项核心特性,它简化了用户界面(UI)与应用程序数据之间的交互。本资料包围绕“WPF Binding”展开,包含源代码,非常适合初学者深入理解和实践。 ### 1. 数据绑定基础 数据绑定...

    WPF.UI-master.zip_WPF_WPF UI_WPF-UI_master ui_wpf.ui

    **WPF(Windows Presentation Foundation)**是微软推出的一种基于.NET Framework的用户界面框架,它为开发者提供了构建桌面应用程序的强大工具。WPF集成了图形、多媒体、数据绑定、样式和模板等众多功能,使得创建...

    WPF的binding代码实例

    在这个“WPF的binding代码实例”中,我们将深入探讨几个基础的绑定用法,帮助开发者更好地理解和应用这一特性。 1. **基本绑定语法** WPF中的数据绑定通常使用`{Binding}`标记来实现。例如,一个`TextBlock`控件的...

    wpf Binding class

    **WPF(Windows Presentation Foundation)**是.NET框架的一部分,它提供了丰富的用户界面(UI)开发能力,包括2D和3D图形、动画、媒体集成以及数据绑定等功能。在WPF中,数据绑定是核心功能之一,它使得UI元素能够...

    File-Manager-UI-Wpf-master.7z

    【标题】"File-Manager-UI-Wpf-master.7z" 涉及的是一个基于WPF(Windows Presentation Foundation)的文件管理器用户界面项目。这个压缩包包含了一个完整的开发环境,供开发者进行学习和使用。 【描述】"自用资源...

    gong-wpf-dragdrop:GongSolutions.WPF.DragDrop库是WPF的拖放框架

    GongSolutions.WPF.DragDrop 一种易于使用的WPF拖放框架。 支持.NET Framework 4.5+和.NET Core 3(3.0和3.1) 产品特点 与MVVM一起使用:拖放的逻辑可以放在ViewModel中。 无需在代码背后放置任何代码,而是将...

    windows-presentation-foundation-4-5renamed_WPF_

    1. **XAML**: XAML(Extensible Application Markup Language)是WPF的核心,它是一种声明式语言,用于描述用户界面和应用逻辑。通过XAML,开发者可以使用XML语法定义UI元素、属性和事件,简化了UI设计过程。 2. **...

    WPF Binding CheatSheet

    在IT领域,尤其是在Windows Presentation Foundation (WPF)框架下,数据绑定(Data Binding)是创建动态用户界面的关键技术之一。WPF Binding CheatSheet提供了一系列快速掌握WPF Data Binding技巧的方法,帮助...

    WPF Binding 学习笔记

    【WPF Binding 学习笔记】 WPF (Windows Presentation Foundation) 的数据绑定是其核心特性之一,它使得UI层和业务逻辑层之间的数据交互变得简单而直观。在WPF中,数据绑定允许UI控件(目标)动态地显示或响应数据...

    Event Binding Markup

    Event Binding Markup Extensions允许开发者在XAML中直接绑定事件,使得UI交互能够驱动业务逻辑。 在WPF 4.5中,引入了对事件处理的增强,使得绑定事件变得更加直观和方便。这些变化主要体现在`EventTrigger`、`...

    WPF Image Base64String 互转 Demo

    WPF提供了一套强大的UI框架,而Base64编码则是一种常见的用于在网络上传输图像数据的方式,因为它可以把二进制数据转化为ASCII字符串。本篇文章将详细讲解如何在WPF中实现Image对象与Base64String之间的转换,以及...

    Pro WPF 4.5 in C# (Pro WPF系列第四版 英文书及其源代码)

    Microsoft's Windows Presentation Foundation (WPF) provides you with a development framework for building high-quality user experiences for the Windows operating system. It blends together rich content...

    ComponentOne Studio for WPF2012 v3 1/3

    FlexGrid for WPF provides built-in printing, cell merging, column aggregation, custom cells, and all the extensibility you need for your business data. Maps Powered By Esri When it comes to ...

    lottie-web-base64:使用Base64处理Lottie-Web图像

    lottie-web-base64 使用Base64处理Lottie-Web图像。 将data.json和图像打包在index.html中。开发npm开始建造电子包装机。 -覆盖用法demo文件夹是UI给定的文件夹,它总是有demo.html,data.json和图片(如果有图片)...

Global site tag (gtag.js) - Google Analytics