如何使用扩展的Tree ItemRenderer更改Flex中Tree控件中节点的外观?

时间:2009-11-04 17:21:51

标签: flex

我正在使用我想要自定义的树控件。树dataProvider中的数据项具有应用于标记节点的属性name,以及应用于选择若干嵌入图像之一的属性type以用作一个图标。最简单的方法是使用labelFieldiconFunction属性。

但是,我想开始使用项目渲染器并打开以后添加更复杂的自定义的大门,所以我尝试制作自己的项目渲染器。我扩展了TreeItemRenderer类,如下所示,并在我的树控件中使用它:

class DirectoryItemRenderer extends TreeItemRenderer
{
  [Embed("assets/directory/DefaultIcon.png")]
  private static var _DEFAULT_ICON:Class;

  // ... some more icons ...

  override public function set data(value:Object):void
  {
    super.data = value; // let the base class take care of everything I didn't think of
    if (value is Node) { // only handle the data if it's our own node class
      switch ((value as Node).type) {
        // ... some case clauses ...
        default:
          this._vSetIcon(_DEFAULT_ICON);
      }
      this.label.text = (value as Node).name;
    }
  }

  private function _vSetIcon(icon:Class):void
  {
    if (null != this.icon && this.contains(this.icon)) {
      this.removeChild(this.icon);
    }
    this.icon = new icon();
    this.addChild(this.icon);
    this.invalidateDisplayList();
  }
}

此代码无效,树控件中的图标和标签保持默认值。使用trace(),我验证了我的代码实际执行完毕。我做错了什么?

2 个答案:

答案 0 :(得分:0)

我可能会尝试一些简单的事情,例如Adobe Cookbooks中的this example。我注意到它们会覆盖updateDisplayList,这可能与您的问题有关。

another example(适用于Flex 2,但看起来适用于Flex 3),它显示了如何管理默认图标。看起来你想要自己管理图标,将默认图标样式设置为null,而不是试图操纵超类的图标属性。

更新 - 查看TreeItemRenderer的来源,commitProperties在检查数据并设置图标和标签之前有以下内容:

if (icon)
{
    removeChild(DisplayObject(icon));
    icon = null;
}

此外,它似乎是data调用invalidateProperties的设置器。因此,当框架调用commitProperties时,您的图标就会被清除。

答案 1 :(得分:0)

查看基础mx.controls.treeClasses.TreeItemRenderer类,我看到updateDisplayList函数中的渲染器从icon获取了disclosureIcon_listData:TeeListData类。不要覆盖updateDisplayList函数,而是尝试使用公共访问器修改icon方法中渲染器的私有disclosureIcon实例的_listData_vSetIcon类,例如这样:

private function _vSetIcon(icon:Class, disclosureIcon:Class = null):void
{
    var tmpListData:TreeListData;   

    if (disclosureIcon == null) disclosureIcon = icon;

    tmpListData = this.listData;
    tmpListData.icon = icon;
    tmpListData.disclosureIcon = disclosureIcon;

    this.listData = tmpListData;
}

编辑

以下是对datalistData之间区别的一些说明。你不得不原谅我对包裹名称的遗漏,但是我正在用我的手机进行编辑,因此很难查找它们,而且我不知道包装名称是否在我的头顶。 data是在TreeItemRenderer界面中IDataRenderer的上下文中定义的。您可以通过实现此接口并定义公共属性data来创建数据渲染器,在这种情况下,公共属性由父控件设置,并包含来自dataProvider的一些数据和元数据。数据渲染器类。

listDataIDropInListItemRenderer接口中定义为BaseListData类型的属性,并在TreeItemRenderer类中实现为属性TreeListData。它与data属性的不同之处在于它包含描述TreeListRenderer本身(图标,缩进,打开)的元数据以及(我相信,稍后我将不得不仔细检查)对正在呈现的数据项的引用。我收集它TreeItemRenderer使用它,我会想象父列表控件用于显示更新和大小调整的目的。有人可以自由纠正或添加,如果我不正确或遗漏了某些东西,我会按照我记得的代码进行修改。

在这种情况下,您希望使用来自数据提供程序的数据集中的元数据来修改确定渲染器显示的数据,因此您需要同时修改它们。

我认为真正的困惑来自于你扩展了TreeItemRenderer类,然后尝试以原始开发人员不打算让某人做的方式覆盖组件上的功能,因此出乎意料结果。如果你的目标是教育而不是易于实现,那么扩展UIComponent类并使用TreeItemRenderer代码作为参考来创建实现相同接口的类可能会更好。这将是对自定义组件开发池的真正潜入。