昨天 Erin 問了一個關於 Flex 4 State Name 問題
Flex 3 State Name 是可以不要寫死,Binding 到一個常數的
可是 Flex 4 卻不能這樣作,因為 Flex 4 多了很多 Inline State 增強語法
這些功能主要都是在編譯期完成的
所以 Flex 4 Compiler 禁止 State Name Binding 功能

Flex 4 文件上的說明 Using Flex 4.5 – Creating view states

Note: View state definitions are processed at compile time. Therefore, you cannot use data binding to set the State.name property because data binding occurs at run time.

測試之後發現,雖然不能用 Binding Expression
但是還是能夠用陳述式修改 State Name 的
只是需要注意的是 currentState 的 name 不能直接變更
否則會出現 Error
須要先建立一個空的 State,並切換 currentState 到這個上
等到所有 State Name 都變更完,再切回來就好了
以下是一次變更所有 State Name 的測試程式:

2011/06/05 更新
之前的寫法有點錯誤
然後拆成外部獨立 StateUtil Class

package {
 import mx.core.UIComponent;
 import mx.states.State;
 
 public class StateUtil {
  public static function setStates(component:UIComponent, stateNames:Array, currentState:String = ""):void {
   var states:Array = component.states;
   if (states.length != stateNames.length) {
    throw new Error("Incorrect Number of State Names Parameter");
    return;
   }
   var tmpState:State = new State();
   tmpState.name = "_tempState_";
   states.push(tmpState);
   component.currentState = "_tempState_";
   for (var i:int = 0; i < stateNames.length; ++i) {
    states[i].name = stateNames[i];
   }
   component.currentState = currentState;
   states.pop();
  }
 }
}

Flex 4 MXML 測試程式:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:s="library://ns.adobe.com/flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx"
  fontSize="14">
 
 <fx:Script>
  <![CDATA[
   public function randomStateNames():void{
    var stateName1:String = "s" + int(Math.random() * 10000);
    var stateName2:String = "s" + int(Math.random() * 10000);
    StateUtil.setStates(this, [stateName1, stateName2], stateName2);
   }
  ]]>
 </fx:Script>
 
 <s:states>
  <s:State id="st1" name="X01"/>
  <s:State id="st2" name="X02"/>
 </s:states>
 
 <s:layout>
  <s:VerticalLayout verticalAlign="middle" horizontalAlign="center"/>
 </s:layout>
 
 <s:Label text="Current State Name: {currentState}"/>
 
 <s:Button height="40" label.X01="Switch to State 02" label.X02="Switch to State 01"
   click.X01="currentState = st2.name;" click.X02="currentState = st1.name;"/>
 
 <s:Button height="40" label="Randomize State Names" click="randomStateNames();"/>
</s:Application>

如此一來,就算不能用 Binding Expression
也能夠將 State Name 拆到外部類別的常數值了
而且任何時候都能夠修改 State Names,Inline State 功能還能正常運作