我是一個新手來flex和建立一個flex 4.5應用程序,它有一個自定義組件擴展SkinnableContainer。這個自定義組件基本上是一種可摺疊面板。當你打開它時,你會看到contentGroup中的所有控件,當你關閉它們時,它們就會消失,你將留下標題。這是通過使contentGroup僅包含在打開狀態中而在皮膚中完成的。如何訪問不可見的Flex組件?
我在應用程序中有一堆這些容器,有些是默認打開的,有些是關閉的。 所以在MXML結構的樣子:
<ui:MyCustomContainer open="false" label="bla">
<s:HGroup>
<s:Button />
<ui:AnotherComponent />
<etc />
</s:HGroup>
</ui:MyCustomContainer>
我的問題是,我無法訪問(通過動作,例如,在事件處理)從封閉容器中的組分(實際上他們的初始化事件代碼不運行),直到他們已被打開至少一次。
做一些挖掘我發現flex有關延遲創建組件的某種性能增強。因此,認爲這必須回答我的SkinnableContainer的creationPolicy設置爲「all」:
<ui:MyCustomContainer open="false" label="bla" creationPolicy="all" >
但是,這是行不通的。有任何想法嗎?
UPDATE:下面
完整的示例Revealer.as的換膚的容器(從書的Flex 4中所採取的行動,並剝離下來比特)
package
{
import flash.events.Event;
import spark.components.SkinnableContainer;
import spark.components.ToggleButton;
import spark.components.supportClasses.TextBase;
[SkinState("open")]
[SkinState("closed")]
[SkinState("disabled")] //Not used: just appeasing compiler in the skin when host component is defined.
[SkinState("normal")] //Not used: just appeasing compiler in the skin when host component is defined.
public class Revealer extends SkinnableContainer
{
private var m_open:Boolean = true;
private var m_label:String;
[SkinPart]
public var toggler:ToggleButton;
[SkinPart(required="false")]
public var labelDisplay:TextBase;
public function Revealer()
{
super();
}
public function get open():Boolean { return m_open; }
public function set open(value:Boolean):void
{
if(m_open == value)
return;
m_open = value;
invalidateSkinState();
invalidateProperties();
}
public function get label():String { return m_label; }
public function set label(value:String):void
{
if(m_label == value)
return;
m_label = value;
if(labelDisplay != null)
labelDisplay.text = value;
}
override protected function getCurrentSkinState():String { return m_open ? "open" : "closed"; }
override protected function partAdded(name:String, instance:Object):void
{
super.partAdded(name, instance);
if(instance == toggler)
{
toggler.addEventListener(Event.CHANGE, toggleButtonChangeHandler);
toggler.selected = m_open;
}
else if(instance == labelDisplay)
{
labelDisplay.text = m_label;
}
}
private function toggleButtonChangeHandler(e:Event):void
{
open = toggler.selected;
}
}
}
RevealerSkin.mxml皮膚爲容器
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<fx:Metadata>[HostComponent("Revealer")]</fx:Metadata>
<s:states>
<s:State name="open" />
<s:State name="closed" />
<s:State name="disabled" /> <!--not used: just appeasing compiler in the skin when host component is defined. -->
<s:State name="normal" /> <!--not used: just appeasing compiler in the skin when host component is defined. -->
</s:states>
<s:Rect radiusX="5" top="0" left="0" right="0" bottom="0" minWidth="200">
<s:stroke><s:SolidColorStroke weight="2" alpha="0.5"/></s:stroke>
</s:Rect>
<s:Group left="0" top="0" right="0" bottom="5">
<s:ToggleButton id="toggler" label="toggle" left="5" top="5" />
</s:Group>
<s:Label id="labelDisplay" left="{toggler.width + 10}" top="10" right="0" />
<s:Group id="contentGroup" includeIn="open" itemCreationPolicy="immediate" left="5" right="5" top="35" bottom="5" />
</s:Skin>
MyControl.mxml放在容器
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
borderWeight="2" borderColor="black"
borderAlpha="0.2" cornerRadius="2"
height="25">
<fx:Script>
<![CDATA[
[Bindable] public var minVal:Number;
[Bindable] public var maxVal:Number;
[Bindable] public var defaultVal:Number;
public function get value():Number { return valueSlider.value; }
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:HGroup width="100%" paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5">
<s:Label text="Value:" />
<s:Spacer width="100%" />
<s:HSlider id="valueSlider" minimum="{minVal}" maximum="{maxVal}" value="{defaultVal}" />
</s:HGroup>
</s:BorderContainer>
RevealerTest.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:local="*"
minWidth="955" minHeight="600" >
<fx:Script>
<![CDATA[
protected function onClick(e:MouseEvent):void {
debugArea.text += control1.value + "\n" + control2.value + "\n";
}
]]>
</fx:Script>
<s:HGroup>
<s:VGroup>
<s:Button label="click me" click="onClick(event)" />
<local:Revealer label="Group 1" skinClass="RevealerSkin" creationPolicy="all">
<local:MyControl id="control1" minVal="0" maxVal="10" defaultVal="5"/>
</local:Revealer>
<local:Revealer label="Group 2" open="false" skinClass="RevealerSkin" creationPolicy="all">
<local:MyControl id="control2" minVal="0" maxVal="100" defaultVal="50"/>
</local:Revealer>
</s:VGroup>
<s:TextArea id="debugArea" />
</s:HGroup>
</s:Application>
注意內部的自定義控件,如果你打我點擊按鈕開幕前第二個容器中,我們無法從初始摺疊組中的控件獲取值。打開組只允許訪問該值。摺疊組仍然沒問題。這是第一次是這個問題。我已將creationPolicy添加到容器並將itemCreationPolicy添加到皮膚中的內容組,但沒有運氣!
謝謝,但沒有奏效。我將itemCreationPolicy =「immediate」添加到了皮膚中的contentGroup,但沒有運氣。我甚至在s:Application級別添加了creationPolicy =「all」,但沒有任何效果。你提到的currentState這個詞和進一步的調查讓我意識到視圖狀態和皮膚狀態之間存在很大的差異。我在這種情況下不使用視圖狀態,而是使用皮膚狀態。 – Richard
仍然,yourSkin.currentState存儲當前的皮膚狀態。您嘗試使用哪種方法訪問contentGroup? – Kodiak
用完整的可重複代碼進行更新以顯示我的意思。 – Richard