如何用mxml继承状态?

Tre*_*eur 9 apache-flex mxml states flex4

我有以下面板组件,名为AdvancedPanel with controlBarContent:

<!-- AdvancedPanel.mxml -->
<s:Panel>
  <s:states>
    <s:State name="normal" />
    <s:State name="edit" />
  </s:states>
  <s:controlBarContent>
    <s:Button 
      includeIn="edit"
      label="Show in edit"
      />
    <s:Button 
      label="Go to edit"
      click="{currentState='edit'}"
      />
  </s:controlBarContent>
</s:Panel>
Run Code Online (Sandbox Code Playgroud)

我创建了第二个面板,名为CustomAdvancedPanel,基于AdvancedPanel,因为我不想重新声明controlBarContent

<!-- CustomAdvancedPanel.mxml -->
<local:AdvancedPanel>
  <s:Button includeIn="edit" label="Extra edit button" />
</local:AdvancedPanel>
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为CustomAdvancedPanel中的"edit"状态未根据编译器声明.我必须在CustomAdvancedPanel.mxml中重新声明编辑状态,如下所示:

  <!-- CustomAdvancedPanel.mxml with edit state redeclared -->
    <local:AdvancedPanel>
      <local:states>
        <s:State name="normal" />
        <s:State name="edit" />
      </local:states>
      <s:Button includeIn="edit" label="Extra edit button" />
    </local:AdvancedPanel>
Run Code Online (Sandbox Code Playgroud)

在应用程序组件中使用CustomAdvancedPanel会显示一个带有"Go to edit"按钮的空面板.但是当我单击它时,"额外编辑按钮"变为可见,但是控制栏内的"在编辑中显示"按钮则不可见.

当CustomAdvancedPanel为空,没有重新声明的状态和"额外编辑按钮"时,面板工作正常.

我认为这是因为在AdvancedPanel中声明的State对象与CustomAdvancedPanel不同,因此状态是不同的,即使它们具有相同的名称.然而.我不能在CustomAdvancedPanel中使用AdvancedPanel的状态而不用(重新)在mxml中声明它们.

有没有办法实现这种状态重用?或者有更好的方法来获得相同的结果吗?

Con*_*ner 2

我建议您使用 Spark 的换肤架构来实现您的目标。因为皮肤状态是在主机组件中继承的,所以您可以以 OOP 方式放置所有逻辑。但皮肤仍然会包含重复的代码:(无论如何,它比所有组件的重复代码要好。

所以我们的 AdvancedPanel 将如下所示:

package
{
    import flash.events.MouseEvent;

    import spark.components.supportClasses.ButtonBase;
    import spark.components.supportClasses.SkinnableComponent;

    [SkinState("edit")]
    [SkinState("normal")]
    public class AdvancedPanel extends SkinnableComponent
    {
        [SkinPart(required="true")]
        public var goToEditButton:ButtonBase;
        [SkinPart(required="true")]
        public var showInEditButton:ButtonBase;

        private var editMode:Boolean;

        override protected function getCurrentSkinState():String
        {
            return editMode ? "edit" : "normal";
        }

        override protected function partAdded(partName:String, instance:Object):void
        {
            super.partAdded(partName, instance);
            if (instance == goToEditButton)
                goToEditButton.addEventListener(MouseEvent.CLICK, onGoToEditButtonClick);
        }

        override protected function partRemoved(partName:String, instance:Object):void
        {
            super.partRemoved(partName, instance);
            if (instance == goToEditButton)
                goToEditButton.removeEventListener(MouseEvent.CLICK, onGoToEditButtonClick);
        }

        private function onGoToEditButtonClick(event:MouseEvent):void
        {
            editMode = true;
            invalidateSkinState();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于 CustomAdvancedPanel:

package
{
    import spark.components.supportClasses.ButtonBase;

    public class CustomAdvancedPanel extends AdvancedPanel
    {
        [SkinPart(required="true")]
        public var extraEditButton:ButtonBase;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以继承Panel类,但我使示例代码更简单。

还有皮肤:

<?xml version="1.0" encoding="utf-8"?>
<!-- AdvancedPanelSkin.mxml -->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Metadata>
        [HostComponent("AdvancedPanel")]
    </fx:Metadata>
    <s:states>
        <s:State name="normal" />
        <s:State name="edit" />
    </s:states>
    <s:Panel left="0" right="0" top="0" bottom="0">
        <s:controlBarContent>
            <s:Button id="showInEditButton" label="Show in edit" includeIn="edit" />
            <s:Button id="goToEditButton" label="Go to edit" />
        </s:controlBarContent>
    </s:Panel>
</s:Skin>
Run Code Online (Sandbox Code Playgroud)

和:

<?xml version="1.0" encoding="utf-8"?>
<!-- CustomAdvancedPanelSkin.mxml -->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Metadata>[HostComponent("CustomAdvancedPanel")]</fx:Metadata>
    <s:states>
        <s:State name="normal" />
        <s:State name="edit" />
    </s:states>
    <s:Panel left="0" right="0" top="0" bottom="0">
        <s:Button includeIn="edit" label="Extra edit button" id="extraEditButton" />
        <s:controlBarContent>
            <s:Button id="showInEditButton" label="Show in edit" includeIn="edit" />
            <s:Button id="goToEditButton" label="Go to edit" />
        </s:controlBarContent>
    </s:Panel>
</s:Skin>
Run Code Online (Sandbox Code Playgroud)