针对 C++ 和 Delphi 的 LiveBindings 一瞥

  • Jonathan Allen
  • 臧秀涛

2013 年 1 月 23 日

话题:C++语言 & 开发

绑定表达式(Binding expression)并不是新概念,XAML 和 Flex 开发者主要就依靠这个。但除 C++/CX(只用于 WinRT 编程)之外,原生编程语言中通常见不到这种概念。不过为 VCL 和 FireMonkey 设计的 LiveBindings 却是个例外。

我们先来介绍一些背景知识。VCL(Visual Component Library)是 Delphi 和 C++ Builder 都支持的老式 UI 框架。它支持 x86 和 x64 模式,但只能运行在 Windows 操作系统上。FireMonkey在新的应用程序中代替了 VCL。它既支持 Windows,也支持 OS X。FileMonkey 和 VCL 可用于同一应用程序中,不过不能用于同一模块中。

据 Embarcadero 介绍:

LiveBindings 基于称作绑定表达式的关系表达式,既可以是单向的,也可以是双向的。LiveBindings 还包括控制对象和源对象。借助绑定表达式,任何对象都可以绑定到其他任何对象,只需要定义包含所要绑定对象的一个或多个属性的绑定表达式。例如,可以把一个 Tedit 控件绑定到一个 Tlabel,这样当编辑框中的文本改变时,标签的标题也会根据绑定表达式计算而得的值自动调整。再举一个例子,把轨迹条控件绑定到进度条,拖动轨迹条时进度条也可以相应变化。

和很多 Delphi/C++ Builder 工具类似,LiveBindings 通常使用 GUI 工具创建。这里有两种选择:LiveBindings DesignerLiveBindings Wizard。这无疑会让习惯于手工编辑 XAML 或 Flex 的绑定表达式的开发者不爽。

请注意,以编程方式编辑绑定是可能的,但强烈建议不要这么做。这方面的文档深埋在一个关于控制台应用的教程中。

与.NET 中要求对象实现某些复杂的设计模式不同,Delphi 和 C++ Builder 中的对象默认就是可绑定的。几乎和所有对象一样,只需要继承TObject,然后像正常情况一样暴露出属性。对 C++ Builder 而言,这意味着要使用__property扩展关键字。

实际应用绑定表达式的代码非常繁琐,不过确实能支持复杂表达式。在下面的例子中,我们可以看到表达式“o1.IntegerValue + o2.IntegerValue”被绑定到了 MyResultObject.IntegerValue 属性。

在 XAML 技术中,绑定表达式是基于事件的。为避免内存泄漏,它们在内部使用了一个“弱事件(weak events)”结构来监控需要通过绑定表达式转发(relay) 的 PropertyChanged 事件。该结构要求所有绑定集中注册,不过事实上大多数开发者并没有意识到这一点。

LiveBindings 缺乏属性变更事件这一概念,因此要进行类似的抽象就不可能了。 虽然 Bindings 仍然是集中注册的,但属性变更时需要显式通知绑定引擎。这通过 Tbindings.Notify 函数完成,该函数接受对象和属性名。

理论上,TBindings.Notify 函数可由属性 setter 调用,而无需客户端代码显式调用。虽然文档没有介绍,但这又带来了多线程相关问题,不过确实消除了对弱事件的需求。

参考英文原文A Look at LiveBindings for C++ and Delphi

C++语言 & 开发