2012-01-30 22 views
5

Tôi có một thành phần Flex 4+ tùy chỉnh mà tôi đang cố gắng thực hiện và có làn da nhận thức được những thay đổi đối với thuộc tính tùy chỉnh. Thuộc tính này sẽ xác định đồ họa trên nút (và một số thay đổi trực quan khác) nhưng dữ liệu sẽ thay đổi liên tục vì nó sẽ được cập nhật bởi bộ hẹn giờ.Flex 4 Custom Component - Làm cách nào để thông báo cho da về những thay đổi về tài sản?

Tôi đã xem các ví dụ chưa được kể và dường như không thể nhận cú pháp chính xác hoặc khám phá cách mọi thứ nên được tách riêng. Tôi đã xem xét commitProperties ghi đè và PropertyChangeEvent mà không thành công. Vì vậy, tôi có hai câu hỏi.

1) Làm cách nào để có thể nhận được thông báo về thuộc tính bị ràng buộc khi thay đổi?

2) Nếu dữ liệu cho thuộc tính bị ràng buộc của thành phần là đối tượng, sẽ ràng buộc hoạt động đúng nếu thuộc tính của đối tượng thay đổi (hoặc tốt hơn là chuyển từng thuộc tính riêng biệt)?

Dưới đây là một ví dụ được rút gọn về những gì tôi đang cố gắng đạt được.

Thành phần trông như thế này:

<s:ButtonBase 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:Script> 
    <![CDATA[ 
     private var _iconData:String; 

     [Bindable] 
     public function get iconData():String 
     { 
      return _iconData; 
     } 
     public function set iconData(value:String):void 
     { 
      _iconData = value; 
     } 
    ]]> 
</fx:Script> 

Tôi gọi nó như thế này:

<components:MyButton id="myButton" iconData="{myData.curIconTag}" skinClass="skins.MyButtonSkin" /> 

Tôi có rất nhiều hình ảnh khác nhau tôi có thể tải và vì vậy tôi 's sợ số lượng các tiểu bang (với sự kết hợp lên/xuống/over/tàn tật, vv có thể nhận được ra khỏi tay để SetIconDisplay được thiết lập các biểu tượng, nhưng thực sự quan trọng là tôi có mã khác trong chức năng đó cần thực thi khi thuộc tính iconData thay đổi sau mỗi X phút. Vì vậy, da là một cái gì đó như thế này:

<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" 
    creationComplete="init()"> 

<fx:Metadata> 
    [HostComponent("components.MyButton")] 
</fx:Metadata> 

<s:states> 
    <s:State name="default" /> 
    <s:State name="down"/> 
    <s:State name="up"/> 
    <s:State name="over"/> 
    <s:State name="disabled" /> 
</s:states> 

<fx:Script> 
    <![CDATA[ 
     import components.MyButton; 

     [Embed(source="images/image1.png")] 
     private var icon1:Class; 

     [Embed(source="images/image2.png")] 
     private var icon2:Class; 

     [Embed(source="images/image3.png")] 
     private var icon3:Class; 

     [Bindable] 
     public var hostComponent:MyButton; 

     [Bindable] 
     private var iconClass:Class; 

     private function init():void 
     { 
      iconClass = new Class(); 
     } 

     // how do I get this called when the iconData property on my custom component is changed? 
     private function SetIconDisplay():void 
     { 
      switch (hostComponent.iconData) 
      { 
       case "apple": 
        iconClass=icon1; 
        break; 
       case "orange": 
        iconClass=icon2; 
        break; 
       case "grape": 
        iconClass=icon3; 
        break; 
      } 
     } 
    ]]>   
</fx:Script> 

<s:BitmapImage source="{iconClass}" x="0" y="0" width="180" height="108"/> 

Một lần nữa, đừng lo lắng nhiều về cách da được thực sự làm những gì nó đang làm như mà có lẽ sẽ thay đổi (không sử dụng tiểu bang). Tôi chỉ cố gắng tìm ra cách gọi một hàm cụ thể khi thuộc tính bị ràng buộc bị thay đổi.

Cảm ơn bạn!

Trả lời

0
<s:BitmapImage source="{hostComponent.iconClass}" /> 

nên làm việc


bạn không cần phải khai báo công var hostComponent: myButton;

nó là một phần của SparkSkin

+1

Hãy nhìn vào mã SparkSkin và bạn sẽ tìm hostComponent đó không phải là một phần của SparkSkin. Tôi tin rằng tài sản được tạo ra tại thời gian biên dịch dựa trên siêu dữ liệu thành phần máy chủ lưu trữ. Điều này có ý nghĩa bởi vì tất cả các skin MXML mở rộng SparkSkin và rằng da không có cách nào để biết loại đối số bất động sản của hostComponent nên là gì. Chỉ trong một ActionScript, bạn phải tạo thuộc tính hostComponent theo cách thủ công. – JeffryHouser

3

Có lớp cơ sở gọi một chức năng trên một làn da đặc biệt có thể nhận được lúng túng, vì nó có nghĩa là lớp cơ sở phụ thuộc vào lớp da, mà làm cho nó khó khăn để trao đổi trên da . Có hai cách tốt để giải quyết vấn đề này:

Tùy chọn 1: Di chuyển biểu tượngĐăng ký vào thành phần. Lớp da có thể liên kết trực tiếp với thuộc tính và logic để quyết định sử dụng biểu tượng nào có thể được xử lý bởi thành phần thay vì da. Điều này giữ logic ra khỏi da, và giữ số lượng mã skinning bạn phải làm việc với xuống.

Tùy chọn 2: Thêm biểu tượngData thuộc tính vào da và liên kết nó với biểu tượng Thuộc tínhData của thành phần máy chủ lưu trữ. Trong hàm setter, gọi SetIconDisplay khi bạn có một giá trị hợp lệ. Điều này giữ cho các biểu tượng được đóng gói trong da, điều này có thể hữu ích nếu bạn muốn sử dụng một làn da rất khác cho cùng một thành phần.

Chỉnh sửa: Nếu bạn đang lập kế hoạch tạo một số giao diện khác không sử dụng biểu tượng, # 2 là cách để thực hiện. Tạo một tài sản trên da như vậy:

private var _iconData:String; 

public function get iconData():String 
{ 
    return _iconData; 
} 

public function set iconData(value:String):void 
{ 
    _iconData = value; 
    SetIconDisplay() 
} 

Sau đó sử dụng một ràng buộc để kết nối nó với các hostComponent:

<fx:Binding source="hostComponent.iconData" destination="iconData" /> 
+0

Thành phần tùy chỉnh rất cơ bản, nhưng tôi sẽ có khoảng 4 hoặc 5 giao diện khác nhau cho nó. Da đặc biệt này khác vì nó có thể có một trong nhiều biểu tượng khác nhau, một số hình ảnh động và những thứ độc đáo khác về nó, nhưng tôi đã vật lộn với thực hành "tốt nhất" cho logic. Logic trong da dường như có ý nghĩa bởi vì nó là mã xác định những gì để hiển thị. Mã trong thành phần dường như không có ý nghĩa bởi vì tôi nghĩ rằng thành phần chính nó không nên biết hoặc quan tâm nó trông như thế nào. Nó chỉ muốn thêm một tài sản cho da để xác định phải làm gì. – ImAStreamer

+0

@ImAStreamer Có vẻ như bạn nên thực hiện phương pháp thứ hai và cập nhật da để lấy thuộc tính iconData. Tôi đã cập nhật câu trả lời với mã yêu cầu. –

+0

Tôi thích cách tiếp cận thứ hai đó. Tôi đã khám phá một cách tiếp cận khác, nó hoạt động. Không chắc chắn sẽ được ưu tiên. Xem câu trả lời của tôi cho câu hỏi của riêng tôi. – ImAStreamer

5

tôi đã kết thúc cử một sự kiện tùy chỉnh khi dữ liệu được cập nhật và lắng nghe cho nó trong da.

Thành phần:

<s:ButtonBase 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:Script> 
     <![CDATA[ 
      import classes.CustomEvent; 

      private var _iconData:String; 

      [Bindable] 
      public function get iconData():String 
      { 
       return _iconData; 
      } 
      public function set iconData(value:String):void 
      { 
       _iconData = value; 
       dispatchEvent(new CustomEvent("iconDataUpdated")); 
      } 
     ]]> 
</fx:Script> 

Da thêm này:

protected function skin_preinitializeHandler(event:FlexEvent):void 
{ 
     hostComponent.addEventListener(CustomEvent.ICON_DATA_UPDATED,SetIconDisplay); 
} 
+0

tốt đẹp một người bạn đời, tôi nghĩ rằng đây là cách để đi bởi vì nếu bạn nhìn vào SparkButtonSkin, nó có mã sau: public function set hostComponent (giá trị: ButtonBase): void { if (_hostComponent) _hostComponent.removeEventListener (" contentChange ", contentChangeHandler); _hostComponent = value; nếu (giá trị) _hostComponent.addEventListener ("contentChange", contentChangeHandler); } – zavr

1

Một giải pháp cho những câu hỏi chung, mặc dù có thể không lý tưởng trong tình huống này, là để gọi da. invalidateDisplayList() bất cứ khi nào một thuộc tính thay đổi. Sau đó, trong da, ghi đè lên chức năng updateDisplayList và từ đó gọi một hàm phản ứng với các thuộc tính đã thay đổi, cũng như gọi hàm trên lớp cha rõ ràng.

Xem ở đây: https://forums.adobe.com/thread/797247

Các vấn đề liên quan