Actionscript 3 - 在列表条目被禁用时从 Combobox Dataprovider(XML 列表)中删除条目

Actionscript3 - Removing entry from Comobox Data Provider (XMLlist) when list entry is disabled

我修改的代码不是我写的,而且我对 Actionscript 的经验很少。

目前,菜单项在禁用时显示为灰色。这是通过以下 类:

实现的
  1. DisabledComboBox(扩展 ComboBox)
  2. DisabledList(扩展列表)
  3. DisabledListItemRenderer(扩展标签)

菜单约束存储在一个大 XML 变量 MenuChoiceXML 中。每个 DisabledComboBox 引用一个 XMLlist,它是 MenuChoiceXML 的一个子集作为它的 DataProviderXMLlists 中的每个列表条目都有一个 elementsID(整数)。

MenuChoiceXML 中还有一个 XMLlist 完整菜单约束,这些约束是根据数据库中可用的内容预先组装的。他们使用以下形式:

也就是说,在一个DisabledComboBox中选择了15,在另一个DisabledComboBoxes中选择了5,12和23,并且它们不能被选择。

与其将它们变灰并禁用选择它们的 MouseEvent,不如将它们从 DataProvider XMLlist.

中完全删除

这些是我认为相关的代码:

约束项XMLlist

<Constraints>
        <Cstr choice="DataProvider1" selectedValue="2" constrains="DataProvider2" denies="4,7,12" />
</Constraints>

TotalStateofProgram.as

 public function applyConstraints():void
{


  // before updating menus all constrained menus enable all menu choices, then turn on restricted options

  for each(var menulist:String in constrainedMenuList)
  {
      for each(var xmlentry:XML in MenuChoicesXML.descendants(menulist).MenuItem)
      {
          xmlentry.@enabled=true;
      }
  }

  // Save constraints in XMLlist
  var cstrs:XMLList = MenuChoicesXML.descendants("Constraints").Cstr;
  // go through each contraint in list of constraints
  for each(var cstr:XML in cstrs)
  {
      var choice:String = cstr.@choice;
      var value:String = cstr.@selectedValue;

      // for each constraint - find if it is required constraint selectedValue matches current selection
      var applies:Boolean = (design.getData(choice) == value);
      if(applies)
      {
          var menuname:String = cstr.@constrains;
          var denies:String = cstr.@denies;
          var deniesarray:Array = denies.split(',');

          // Go throught items which are denied by selection
          for(var i:int = 0; i<deniesarray.length;i++) 
          {
              var d:String = deniesarray[i];

              // If something that is to be constrained is currently selected, unselect it from DisabledComboBox
              if(design.getData(menuname) == d) 
                  design.setData(menuname, "0"); // default elementsId for unselected is 0


              // set disable menu choice for this elementsId  
              (MenuChoicesXML.descendants(menuname).MenuItem.(@elementsId == d)).@enabled = "false";

          } 
      }
  }
}

前面的代码重置了所有约束,然后使用当前选择的菜单项将约束应用于其他菜单项。重要的一点是这一行:

(MenuChoicesXML.descendants(menuname).MenuItem.(@elementsId == d)).@enabled = "false";

它似乎正在查找 XMLlist 中的项目并将其禁用。禁用后,DisabledListDisabledListItemRenderer 会看到这一点,其中所选项目变为灰色并且附加到它的 MouseEvent 被禁用。 (我将 post 稍后实现的代码,因为我不是 100% 相关)

我意识到通常使用 ComboBox.removeItem(),但我不确定如何使用 elementsID 查找 ComboBoxDataProvider(如上所示) ).

以下是我的一些问题:

我将致力于总结使 DataProvider 的列表条目变灰的代码。我不确定它是否相关,因为变灰是对构成 DisabledComboBoxDataProvider 的列表中的文本执行的,但是我想从 DisabledCombobox 中删除该元素(这看起来工作量少了)。

可能相关代码:

DisabledComboBox.as

package com.cwmlib.controls
{
    import mx.controls.ComboBox;
    import mx.core.ClassFactory;
    import mx.events.FlexEvent;

    public class DisabledComboBox extends ComboBox
    {
        public function DisabledComboBox()
        {

            super();

            this.dropdownFactory = new ClassFactory(DisabledList);

            this.itemRenderer = new ClassFactory(DisabledListItemRenderer);

        }
    }
}

DisabledList.as

package com.cwmlib.controls
{
    import flash.events.MouseEvent;
    import flash.events.KeyboardEvent;
    import mx.controls.ComboBox;
    import mx.core.ClassFactory;
    import mx.controls.List;
    import mx.controls.listClasses.IListItemRenderer;
    import mx.controls.listClasses.ListItemRenderer;

    public class DisabledList extends List
    {


        public function DisabledList()
        {

            super();
            this.itemRenderer = new ClassFactory(DisabledListItemRenderer);

        }

        private function itemDisable(event:MouseEvent):Boolean
        {
            var item:IListItemRenderer = mouseEventToItemRenderer(event);

            if (item != null && item.data != null
                 && ((item.data is XML && item.data.@enabled == 'false')
                || item.data.enabled==false || item.data.enabled=='false')
                ) 
            {
                  return true;
            } 
            else 
            {
                  return false;
            }

        }   
    }
}

DisabledListItemRenderer.as

package com.cwmlib.controls
{
    import mx.controls.Label;

    public class DisabledListItemRenderer extends Label
    {
        private var _enabled:Boolean = true;

        public function DisabledListItemRenderer()
        {

              super();

        }    



        override public function set data(value:Object):void
        {

            if (value != null && ((value is XML && value.@enabled == 'false')
                || value.enabled == false || value.enabled == 'false')
            ){

                this._enabled = false;

            }
            else
            {
                  this._enabled = true;

            }

            super.data = value;

        }    



        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {

            super.updateDisplayList(unscaledWidth, unscaledHeight);

            if (!this._enabled) {
                textField.setColor(getStyle("disabledColor"));
            }
            else
            {
                textField.setColor(getStyle("color"));
            }
        }
    }
}

如果您 select 在另一个组合框中删除某些项目,那么您想删除一个组合框中的某些项目吗?如果您 select 其他东西,可能会再次显示它们?在这种情况下,filterFunction 听起来是合适的工具。未经测试,但这会给你一个想法:

// make a dedicated _myDataProvider for the filtered combobox and assign a filterfunction to it
_myDataProvider.filterFunction = filterCollection;

// Assign the dataProvider
filteredCombobox.dataProvider = _myDataProvider;

// filter the dataprovider when selection in the first combobox will change
selectionComboBox.addEventListener(Event.CHANGE, onComboBoxChange);


private function onComboBoxChange(e:Event):void
{
    // refresh the dataprovider, that will apply the filter
    _myDataProvider.refresh();
}

private function filterCollection(item:Object):Boolean
{
    // here you need to know the condition for the filter depending on the selection in the first combobox (prbably the selected item in the selection combobox?)
    // this filterCollection function will run trough each item in the _myDataProvider and return true (keep the item in the list) or false (the item will disappear)               
    if (condition)
        return true;
    else
        return false;
}

请记住,应用过滤器后,_myDataProvider 将仅包含当前可见的项目。如果您再次需要完整的集合,您可以使用

重置数据提供者
_myDataprovider.filterFunction = null;
_myDataprvider.refresh();

编辑:

整个 XML 操作对我来说听起来很痛苦。摆脱自定义组合框和 XML。解析您的 XML 并制作两个数据提供者 - 一个用于 selection 组合框,它将具有值对象,此拒绝 属性:

public class SelectionVO
{
    public var label:String;
    public var denies:Array; // for example, ["2", "3", "4"];
}

还有一个用于过滤组合框的值对象,该对象将具有用于检查是否应过滤掉该项目的 ID:

public class FilteredItemVO
{
    public var label:String;
    public var myID:String; // for example, "3"
}

然后当 selection 组合框发生变化时,您可以过滤集合:

private function filterCollection(item:Object):Boolean
{
    var selectedVO:SelectionVO = selectionComboBox.selectedItem as SelectionVO;

    // show this item if its myID is NOT included in the selected vo's denies array
    if (selectedVO:SelectionVO.denies.indexOf(item.myID) == -1)
        return true;
    else
        return false;
}