原文 http://www.11011.net/wpf-binding-expressions

Back in April I posted an idea for building an expression converter for use with MultiBindings. This is a question I often see asked, but the answer is usually "go and write a once off converter" (for an example see the Negate converter in my Transition sample - how useful is that really?). More recently I noticed this sample on LearnWPF which provides single value simple arithmetic conversions. Unfortunately no one ever took the bait and implemented the multi-value converter, so I had to go and do it myself.

The result is the JScriptConverter, which for simplicity of use is both an IMultiValueConverter and an IValueConverter. There are numerous benefits to using JScript here:

  1. It's part of the framework, so we don't have to go and write our own scanner/parser/interpreter for a new mini language.
  2. It's a dynamic language, so it nicely complements the dynamically typed binding system of WPF.
  3. Evaluations in JScript are interpreted not compiled, so we don't leak memory on every evaluation.

The code for the conveter is once again quite trivial. Because it's quite difficult to set up a JScript environment for evaluation I instead compile a tiny JScript assembly to wrap the evaluations. This is done once statically and then reused by all instances of the class. Note the TrapExceptions property, if this is set to true any exceptions raised during the conversion will result in null.

Using it is easy. Just instantitate the converter as a resource:

<utils:JScriptConverterx:Key="JScript"TrapExceptions="False" />

And wire it up as a single Binding:

<TextBlockText="{Binding ElementName=tb1, Path=Text,
Converter={StaticResource JScript},
ConverterParameter=Int32.Parse(values[0])/100.0"/>

Or as a MultiBinding:

<MultiBindingConverter="{StaticResource JScript}"ConverterParameter=
"new System.Windows.Thickness(values[0]*0.1/2,values[1]*0.1/2,0,0)">
<BindingRelativeSource="{RelativeSource TemplatedParent}"Path="ActualWidth" />
<BindingRelativeSource="{RelativeSource TemplatedParent}"Path="ActualHeight" />
</MultiBinding>

I'm not so happy with the code that enumerates and adds references to all the Assemblies in the current AppDomain, but for the time being it serves its purpose.

Anyway, without further ado (of course this requires a reference to Microsoft.JScript). Cut and paste as you please:

using System;
using System.Windows.Data;
using System.CodeDom.Compiler;
using System.Reflection; namespace Utils.Avalon
{
public sealed class JScriptConverter : IMultiValueConverter, IValueConverter
{
private delegate object Evaluator(string code, object[] values);
private static Evaluator evaluator; static JScriptConverter()
{
string source =
@"import System; class Eval
{
public function Evaluate(code : String, values : Object[]) : Object
{
return eval(code);
}
}"; CompilerParameters cp = new CompilerParameters();
cp.GenerateInMemory = true;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
if (System.IO.File.Exists(assembly.Location))
cp.ReferencedAssemblies.Add(assembly.Location); CompilerResults results = (new Microsoft.JScript.JScriptCodeProvider())
.CompileAssemblyFromSource(cp, source); Assembly result = results.CompiledAssembly; Type eval = result.GetType("Eval"); evaluator = (Delegate.CreateDelegate(
typeof(Evaluator),
Activator.CreateInstance(eval),
"Evaluate") as Evaluator);
} private bool trap = false;
public bool TrapExceptions
{
get { return this.trap; }
set { this.trap = true; }
} public object Convert(object[] values, System.Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
try
{
return evaluator(parameter.ToString(), values);
}
catch
{
if (trap)
return null;
else
throw;
}
} public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return Convert(new object[] { value }, targetType, parameter, culture);
} public object[] ConvertBack(object value, System.Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotSupportedException();
} public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotSupportedException();
}
}
}

Impossible WPF Part 2: Binding Expressions的更多相关文章

  1. Impossible WPF Part 1: Binding Properties

    原文 http://www.11011.net/wpf-binding-properties Ever wanted to write the following? <RichTextBoxDo ...

  2. 【转】WPF中的Binding技巧(二)

    WPF中的Binding技巧(二)     接上篇, 我们来看一看Elementname,Source,RelativeSource 三种绑定的方式 1.ElementName顾名思义就是根据Ui元素 ...

  3. [XAML]类似WPF绑定的Binding的读取方法

    在WPF的XAML里,依赖属性可以使用基于BindingBase之类的MarkupExtensin 读取XAML时,会自动的把该BindingBase转换为BindingExpressionBase ...

  4. [WPF系列]-使用Binding来同步不同控件的Dependency property

    简介 项目中经常会用到,同步两个控件的值,本文就简单列举两种方式来同步不同控件的两个Dependency Property. 示例 效果图: 只使用C#代码: //获取slider1的ValueDep ...

  5. (WPF) 再议binding:点击User Control时,User Control变换颜色或做其他的处理。

    Binding 是前台UI(显示层)和后台代码(数据层)的桥梁.理论上当后台的数据变动时,显示的数据或样式应该随之而变.这些是动态的. 对于Binding的设置可以在前台Xaml,也可以在后台Code ...

  6. 解读WPF中的Binding

    1.Overview 基于MVVM实现一段绑定大伙都不陌生,Binding是wpf整个体系中最核心的对象之一这里就来解读一下我花了纯两周时间有哪些秘密.这里我先提出几个问题应该是大家感兴趣的,如下: ...

  7. (WPF, MVVM) Textbox Binding

    参考:http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger(v=vs.110).aspx Te ...

  8. (WPF, MVVM) Slider Binding.

    对于Button的Command的绑定可以通过实现ICommand接口来进行,但是Slider并没有Command属性. 另外如果要实现MVVM模式的话,需要将一些Method和Slider的Even ...

  9. (WPF) MVVM: DataGrid Binding

    Binding到DataGrid的时候,需要用到ObservableCollection. public ObservableCollection<Customer> Customers ...

随机推荐

  1. C++ enum 作用域问题和解决方案

    C++ 中的枚举类型继承于 C 语言.就像其他从 C 语言继承过来的很多特性一样,C++ 枚举也有缺点,这其中最显著的莫过于作用域问题--在枚举类型中定义的常量,属于定义枚举的作用域,而不属于这个枚举 ...

  2. 网上下载的“上下3D”和“左右3D”影片该如何播放?

    我们平常买的红蓝3D眼镜智能播放红蓝3D片源.网上找3D电影的时候,虽试图去找红蓝3D格式电影,但总会找到不少“左右格式”或者"上下格式"影片.正常播放后发现有两重画面.这种3D电 ...

  3. dubbo服务者配置说明

    <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright 1999-2011 Aliba ...

  4. 讲讲金融业务(一)--自助结算终端POS

    之前在群里和大家聊天的时候,发现好多人对银行业务比較感兴趣,或许是由于大家对银行不了解,以为非常神奇的样子.全部,从这周開始我打算把我肚子里的墨水慢慢地倒出来,和大家分享分享.   在技术还不发达的时 ...

  5. Python+Django+SAE系列教程9-----Django的视图和URL

    第三.四.五章介绍的就是Django中MVC的视图.模板.模型了. 首先来看视图(view),在用Django生成的站点目录中,创建一个view.py文件,这个文件開始是空的.然后我们输入下面内容: ...

  6. JS于,子类调用父类的函数

    概要 JS虽然没有直接有面向对象的特性,但还是能prototype为了模拟面向对象的特性,如继承和多态.而大多数面向对象的语言(例如C++.Java等一下)相比,JS为了实现面向对象还是有点繁琐,抽象 ...

  7. 积跬步,聚小流------关于UML类图

    UML的存在 类图是使用频率比較高的UML图,它用于描写叙述系统中所含的类以及它们之间的相互关系,帮助人们简化对系统的理解,也是系统分析和设计阶段的重要产物,也是系统编码和測试的重要类型根据. UML ...

  8. 一些常用的Intent及intent-filter的信息

    Uri Action 功能 备注 geo:latitude,longitude Intent.ACTION_VIEW 打开地图应用程序并显示指定的经纬度   geo:0,0?q=street+addr ...

  9. 悬浮二维码 QQ ToTop

    //回顶部 <div id="lqdbe" style="position: absolute; visibility: visible; z-index: 1;  ...

  10. C# Programming Study #2

    readonly (C# Reference) readonly  关键字是可以在字段上使用的修饰符.  当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者 ...