原文 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. Protel 99SE PCB 打印技巧

    1. 打开 Protel99SE PCB 设计文档.从菜单File 下单击Print/Preview 打印预览菜单.出现PCB 打印预览介面. 2.从File 下单击 Setup Printer 设置 ...

  2. 浅谈USB设备的VID和PID

    根据USB规范的规定,所有的USB设备都有供应商ID(VID)和产品识别码(PID),主机通过不同的VID和PID来区别不同的设备,VID和PID都是两个字节长,其中,供应商ID(VID)由供应商向U ...

  3. dump文件定位程序崩溃代码行

    1.dump文件 2.程序对应的pdb 步骤一:安装windbg 步骤二:通过windbg打开crash dump文件 步骤三:设置pdb文件路径,即符号表路径 步骤四:运行命令!analyze -v ...

  4. 软件包管理_rpm命令管理_yum工具管理_文件归档压缩_源码包管理

    rpm命令管理软件 对于挂载的像U盘那种都会在midea目录下,但是会显示在桌面上 安装软件(i:install,v:verbose冗长的,h:human):rpm  -ivh  xxxx.rpm 安 ...

  5. VS前台设计中的缺陷

    程序的前台界面设计我一般都是Blend中完成的,因为在VS中前台比较难控制.而效果之内的就更不用说了.今天写了个小程序用来启动其他程序的.运行界面如下: 这是尺寸和距离刚刚好的,我们去Blend当中看 ...

  6. nginx启动、开机自启动、重启、关闭

    yum -y  install nginx # yum info nginx Loaded plugins: fastestmirror Loading mirror speeds from cach ...

  7. HDU-4866-Shooting(函数式线段树)

    Problem Description In the shooting game, the player can choose to stand in the position of [1, X] t ...

  8. 【node.js】本地模式安装express:'express' 不是内部或外部命令,也不是可运行的程序或批处理文件。

    今天闲来无事想起了node.js,因此到网上下载了一个node.js的安装程序进行安装.其中: 安装程序:node-v0.11.13-x64.msi PC系统:Windows 7 自定义安装路径:D: ...

  9. How Many Answers Are Wrong(并查集)

    Description TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he ...

  10. 移除Strorefront站点footer上的Storefront Design By WooThemes字样

    进入wp-content\themes\storefront\inc\structure\footer.php, 注释掉代码: if ( ! function_exists( 'storefront_ ...