13

到目前为止,我只做了一点 Flex 开发,但我更喜欢以编程方式创建控件而不是 mxml 文件的方法,因为(如果我错了,纠正我!)我已经收集到你可以'不能兼得——也就是说,在单独的 ActionScript 类文件中具有类功能,但在 mxml 中声明包含的元素。

在生产力方面似乎没有太大差异,但以编程方式进行数据绑定似乎并不简单。我看了一下 mxml 编译器如何转换数据绑定表达式。结果是一堆生成的回调和比 mxml 表示中更多的行。那么问题来了:有没有一种方法可以以编程方式进行数据绑定,而不会造成伤害?

4

4 回答 4

29

不要害怕 MXML。它非常适合布置视图。如果您编写自己的可重用组件,那么在 ActionScript 中编写它们有时可能会给您更多的控制权,但对于不可重用的视图,MXML 更好。它更简洁,绑定非常容易设置,等等。

但是,纯 ActionScript 中的绑定不必那么痛苦。它永远不会像在 MXML 中为您完成很多事情那样简单,但它可以不费力气地完成。

你所拥有的是BindingUtils和它的方法bindSetterbindProperty。我几乎总是使用前者,因为我通常想做一些工作,或者invalidateProperties在值更改时调用,我几乎从不想设置一个属性。

您需要知道的是,这两个返回一个类型为 的对象ChangeWatcher,如果您出于某种原因要删除绑定,则必须保留该对象。这就是使 ActionScript 中的手动绑定不如 MXML 中方便的原因。

让我们从一个简单的例子开始:

BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");

这设置了一个绑定,该绑定将在变量中对象的属性更改nameChanged时调用该方法。该方法将接收属性的新值作为参数,因此它应该如下所示:nameselectedEmployeenameChangedname

private function nameChanged( newName : String ) : void 

这个简单示例的问题在于,一旦您设置了此绑定,它将在每次指定对象的属性更改时触发。变量的值selectedEmployee可能会改变,但仍然为变量之前指向的对象设置了绑定。

有两种方法可以解决这个问题:要么保留aroundChangeWatcher返回的BindingUtils.bindSetter值,并在你想删除绑定时调用unwatch它(然后设置一个新的绑定),或者绑定到你自己。我将首先向您展示第一个选项,然后解释我所说的绑定到自己的意思。

可以将currentEmployee其制成 getter/setter 对并像这样实现(仅显示 setter):

public function set currentEmployee( employee : Employee ) : void {
    if ( _currentEmployee != employee ) {
        if ( _currentEmployee != null ) {
            currentEmployeeNameCW.unwatch();
        }

        _currentEmployee = employee;

        if ( _currentEmployee != null ) {
            currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
        }
    }
}

发生的情况是,当设置currentEmployee属性时,它会查看是否存在先前的值,如果是,则删除该对象的绑定 ( currentEmployeeNameCW.unwatch()),然后设置私有变量,除非新值null设置为新绑定为name财产。最重要的是它保存了ChangeWatcher绑定调用返回的内容。

这是一个基本的绑定模式,我认为它工作得很好。然而,有一个技巧可以让它变得更简单一些。您可以改为绑定到自己。currentEmployee您可以让绑定系统为您完成,而不是每次属性更改时都设置和删除绑定。在您的creationComplete处理程序(或构造函数或至少提前一段时间)中,您可以像这样设置绑定:

BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);

这不仅设置了与 上的currentEmployee属性的绑定this,而且还设置了name与此对象上的属性的绑定。因此,无论何时更改,currentEmployeeNameChanged都会调用该方法。无需保存,ChangeWatcher因为永远不必删除绑定。

第二个解决方案在很多情况下都有效,但我发现第一个解决方案有时是必要的,尤其是在使用非视图类中的绑定时(因为this必须是事件调度程序并且currentEmployee必须是可绑定的才能工作) .

于 2008-08-18T06:56:22.250 回答
8

它存在于今天。:)

我刚刚将我的 ActionScript 数据绑定项目作为开源发布:http ://code.google.com/p/bindage-tools

BindageTools 是 BindingUtils 的替代品(参见那里的文字游戏?),它使用流畅的 API,您可以在管道样式中声明数据绑定:

Bind.fromProperty(person, "firstName")
    .toProperty(firstNameInput, "text");

双向绑定:

Bind.twoWay(
    Bind.fromProperty(person, "firstName"),
    Bind.fromProperty(firstNameInput, "text"));

显式数据转换和验证:

Bind.twoWay(
    Bind.fromProperty(person, "age")
        .convert(valueToString()),
    Bind.fromProperty(ageInput, "text")
        .validate(isNumeric()) // (Hamcrest-as3 matcher)
        .convert(toNumber()));

等等。网站上有更多的例子。还有很多其他功能,快来看看吧。 - 马修

编辑:更新的 API

于 2011-04-02T05:58:23.443 回答
2

将组件的 MXML 和 ActionScript 分离到单独文件中的一种方法是执行类似于 ASP.Net 1.x 代码隐藏模型的操作。在此模型中,声明部分(在本例中为 MXML)是命令部分(ActionScript)的子类。所以我可能会为这样的类声明代码:

package CustomComponents
{
    import mx.containers.*;
    import mx.controls.*;
    import flash.events.Event;

    public class MyCanvasCode extends Canvas
    {
        public var myLabel : Label;

        protected function onInitialize(event : Event):void
        {
            MyLabel.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.";
        }
    }
}

...和这样的标记:

<?xml version="1.0" encoding="utf-8"?>
<MyCanvasCode xmlns="CustomComponents.*" 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="onInitialize(event)">
    <mx:Label id="myLabel"/>    
</MyCanvasCode>

从这个例子可以看出,这种方法的一个缺点是你必须在两个文件中声明像myLabel这样的控件。

于 2008-08-30T14:54:16.723 回答
0

我通常使用一种方法将 mxml 和动作脚本一起使用:我所有的 mxml 组件都继承自一个动作脚本类,我在其中添加了更复杂的代码。然后可以在mxml文件中引用这个类中实现的事件监听器。

问候,

露丝

于 2009-02-04T14:49:59.940 回答