ASP NET, NET Framework, MONO, SQL, Visual Studio | Professional Programs | Программист Еремин В.В.
(Flex) Flex (2012 год)

Обработка собственных событий из ItemRenderer

To view this page ensure that Adobe Flash Player version 11.1.0 or greater is installed.



Основной элемент отображения периодических данных во Флекс - DataGroup / ItemRenderer (и всевозможные их производные, вроде Custom ItemRenderer ). DataGroup фактически во флексе играет ту же роль, что и DataList в ASP.NET - то есть без них никуда. Базовый пример использования DataGroup-ItemRenderer вы можете у меня в блоге - Как создавать простые тетрис-подобные аркады на Флексе за несколько кликов мышкой.

Но когда мне потребовалось обработать собственное событие, создаваемое в ItemRenderer - я сразу и не сообразил как, пришлось взглянуть в инете. Оказалось что прицепить у элементов подобных s:DataGroup прицепить обработчики ItemRenderer можно только в событии updateComplete элемента s:DataGroup. Чтобы эта фишка не забылось (и другим это будет полезно) - я решил написать эту небольшую ремарку.

Конечно, вживую на сайте, это все вычитывается web-сервисами из базы, но для этой заметки такой пример был бы бессмысленным - билеты раскупят и web-сервис по этому отбору будет вызвращать пустой набор билетов. Смысл и код этой маленькой заметочки будет утерян. Поэтому я сделал снимок данных, возвращаемых web-сервисом из базы (так как я описал тут Флекс-сериализаторы. Сериализация/десеализация FLAME вышла вполне точной, за исключением рекурсивного ENUM - как видите, это я поправил вручную.

Итак, приложение, которое вы видите в этой заметке - выглядит вот так:


   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
   3:                 xmlns:s="library://ns.adobe.com/flex/spark" 
   4:                 xmlns:mx="library://ns.adobe.com/flex/mx" 
   5:                 minWidth="654" width="654" 
   6:                 applicationComplete="application1_applicationCompleteHandler(event)"  backgroundColor="#FDF5E6" height="400" minHeight="400">
   7:      <fx:Script>
   8:          <![CDATA[
   9:              import adobe.utils.CustomActions;
  10:              import adobe.utils.XMLUI;
  11:   
  12:              import flame.serialization.JSONSerializer;
  13:   
  14:              import mx.collections.ArrayCollection;
  15:              import mx.controls.Alert;
  16:              import mx.events.FlexEvent;
  17:              import mx.managers.BrowserManager;
  18:              import mx.managers.IBrowserManager;
  19:              import mx.utils.StringUtil;
  20:              
  21:              [Bindable]
  22:              protected var Tickets:ArrayCollection;
  23:              
  24:              [Embed(source="WebServiceResult.txt",mimeType="application/octet-stream")]
  25:              private var JSON_text : Class;
  26:              
  27:              
  28:              protected function application1_applicationCompleteHandler(event:FlexEvent):void
  29:              {
  30:                  var JSONtext:ByteArray = new JSON_text() as ByteArray;
  31:                  var JSONstr:String= JSONtext.readUTFBytes(JSONtext.length);
  32:                  var Flame:flame.serialization.JSONSerializer = new flame.serialization.JSONSerializer
  33:                  var X = Flame.deserialize(JSONstr);
  34:                  Tickets = new ArrayCollection;
  35:                  for (var i:int=0;i<X.length;i++){
  36:                      X.source[i].TicketType = TicketType.Good;
  37:                      Tickets.addItem(X.source[i]);
  38:                  }
  39:                  WebServiceEnd();
  40:              }
  41:              
  42:              //все обращения к сервисам завершились -> все вычитанные данные в Tickets 
  43:              protected function WebServiceEnd():void{
  44:                  if (TicketsGroup.dataProvider!==null){
  45:                      TicketsGroup.dataProvider.removeAll();
  46:                      TicketsGroup.validateNow();
  47:                      TicketsGroup.dataProvider=Tickets;
  48:                      TicketsGroup.validateNow();
  49:                  }
  50:                  else {
  51:                      TicketsGroup.invalidateDisplayList();
  52:                      TicketsGroup.dataProvider=Tickets;
  53:                  }
  54:              }
  55:              
  56:              protected function TicketsGroup_updateCompleteHandler(event:FlexEvent):void
  57:              {
  58:                  for (var i:int=0;i<TicketsGroup.numElements;i++){
  59:                      var TicketView1:OneTicketView = TicketsGroup.getElementAt(i) as OneTicketView;
  60:                      TicketView1.addEventListener("TicketSelected", TickedSelected_event);
  61:                  }
  62:              }
  63:              
  64:              protected function TickedSelected_event(e:Event):void{
  65:                  URL1.text = (e.currentTarget as OneTicketView).SelectedTicketID;
  66:                  //var RedirectURL:String = FormatURL(URL_Parm.IsDirection, URL_Parm.IsReturn, URL_Parm.FromDate, URL_Parm.ToDate, SelectedTicketID);
  67:                  //flash.net.navigateToURL(new URLRequest("Zakaz.aspx#" + RedirectURL),"_self");
  68:              }
  69:   
  70:              import mx.collections.ArrayCollection;
  71:              import mx.collections.ArrayList;
  72:              
  73:              protected function FormatURL(IsDirection:Boolean, IsReturn:Boolean, FromDate:String, ToDate:String, ID:String):String{
  74:                  return mx.utils.StringUtil.substitute("Direction={0},Return={1},FromDate={2},ToDate={3},CN={4}", IsDirection, IsReturn, FromDate, ToDate, ID);
  75:              } 
  76:              
  77:          ]]>
  78:      </fx:Script>
  79:   
  80:      <s:DataGroup id="TicketsGroup" x="0" y="40" width="100%" height="100%"  itemRenderer="OneTicketView"  updateComplete="TicketsGroup_updateCompleteHandler(event)">
  81:          <s:layout>
  82:              <s:VerticalLayout gap="20"/>
  83:          </s:layout>
  84:      </s:DataGroup>
  85:      <s:Label x="50" y="10" width="553" id="URL1"/>
  86:          
  87:  </s:Application>

Ключик - привязку к собственному событию ItemRenderer - вы видите в строке 60, ну а теперь собственно код рендерера:


   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <s:ItemRenderer  xmlns:fx="http://ns.adobe.com/mxml/2009" 
   3:                     xmlns:s="library://ns.adobe.com/flex/spark" 
   4:                     xmlns:mx="library://ns.adobe.com/flex/mx" width="654" height="100" 
   5:                     creationComplete="bordercontainer1_contentCreationCompleteHandler(event)" 
   6:                     contentBackgroundColor="#FDF5E6">
   7:      
   8:      <fx:Metadata>
   9:          [Event(name="TicketSelected", type="flash.events.Event")]
  10:      </fx:Metadata>
  11:      
  12:      <fx:Script>
  13:          <![CDATA[
  14:              import mx.controls.Alert;
  15:              import mx.events.FlexEvent;
  16:   
  17:              [Embed(source="../Images/back.png")]
  18:              [Bindable]
  ....   
  41:              [Embed(source="../Images/z4.jpg")]
  42:              [Bindable]
  43:              public var RedImage:Class;
  44:              
  45:          
  46:              private var _TicketType:TicketType;
  47:              private var _USDCurs:Number;
  48:              private var _DirectTicketInfo;
  49:              private var _ReturnTicketInfo;
  50:              
  51:              protected function FormatPrice():String{
  52:                  var NF:NumberFormatter = new NumberFormatter();
  53:                  var DirectCost:Number=0;
  54:                  var ReturnCost:Number=0;
  55:                  var RubCost:Number;
  56:                  if (_DirectTicketInfo !==null){
  57:                      DirectCost = _DirectTicketInfo.Price;
  58:                  }
  59:                  if (_ReturnTicketInfo!==null){
  60:                      ReturnCost = _ReturnTicketInfo.Price;
  61:                  }
  62:                  RubCost = _USDCurs * (DirectCost + ReturnCost);
  63:                  return NF.format(RubCost);    
  64:              }
  65:              
  66:              
  67:              protected function bordercontainer1_contentCreationCompleteHandler(event:FlexEvent):void
  68:              {
  69:                  _TicketType = data.TicketType;
  70:                  _USDCurs  = data.USDCurs;
  71:                  _DirectTicketInfo = data.DirectTicketInfo;
  72:                  _ReturnTicketInfo = data.ReturnTicketInfo;
  73:                  if (_DirectTicketInfo !== null){
  74:                      L1.text = FormatDayNames(_DirectTicketInfo.FromDate);
  75:                      L2.text = _DirectTicketInfo.FromAirport + "  " + _DirectTicketInfo.FromTime;
  76:                      L3.text = _DirectTicketInfo.ToAirport + "  " + _DirectTicketInfo.FlyTime;
  77:                      L4.text = _DirectTicketInfo.AviaCompanyCode + "  " + _DirectTicketInfo.FlyNumber;
  78:                      L5.text = _DirectTicketInfo.HowMany;
  79:                  }
  80:                  if (_DirectTicketInfo.HowMany=="Есть" ||  _DirectTicketInfo.HowMany=="есть" ){
  81:                      Dir.source = YesImage;
  82:                  }
  83:                  else{
  84:                      Dir.source = NoImage;
  85:                  }
  86:                  if (_ReturnTicketInfo !== null){
  87:                      M1.text = FormatDayNames(_ReturnTicketInfo.FromDate);
  88:                      M2.text = _ReturnTicketInfo.FromAirport + "  " + _ReturnTicketInfo.FromTime;
  89:                      M3.text = _ReturnTicketInfo.ToAirport + "  " + _ReturnTicketInfo.FlyTime;
  90:                      M4.text = _ReturnTicketInfo.AviaCompanyCode + "  " + _ReturnTicketInfo.FlyNumber;
  91:                      M5.text = _ReturnTicketInfo.HowMany;
  92:                      if (_ReturnTicketInfo.HowMany=="Есть" ||  _ReturnTicketInfo.HowMany=="есть" ){
  93:                          Ret.source = YesImage;
  94:                      }
  95:                      else{
  96:                          Ret.source = NoImage;
  97:                      }    
  98:                  }
  99:                  lCost.text = FormatPrice();
 100:              }
 101:              
 102:              public var SelectedTicketID:String;
 103:              protected function image1_clickHandler(event:MouseEvent):void
 104:              {
 105:                  if (_DirectTicketInfo !== null){
 106:                      SelectedTicketID = _DirectTicketInfo.ID
 107:                  } 
 108:                  if (SelectedTicketID !== ""){
 109:                      SelectedTicketID += "_"
 110:                  }
 111:                  if (_ReturnTicketInfo !== null){
 112:                      SelectedTicketID += _ReturnTicketInfo.ID
 113:                  }
 114:                  dispatchEvent(new Event("TicketSelected", true));
 115:              }
 116:   
 117:          ]]>
 118:      </fx:Script>
 119:      
 120:      <fx:Script source="DateFunction.as" />
 121:      
 122:      <fx:Declarations>
 123:          <!-- Place non-visual elements (e.g., services, value objects) here -->
 124:      </fx:Declarations>
 125:      <s:BorderContainer x="0" y="0"  width="654" height="100" backgroundImage="{BackImage}" borderVisible="false" backgroundColor="#FDF5E6">
 126:          <mx:Image id="A1" x="563" y="50" width="91" height="41" useHandCursor="true" buttonMode="true" mouseOver="A1.source=RedImage"  mouseOut="A1.source=OkButtImage" click="image1_clickHandler(event)" source="{OkButtImage}"/>
 127:          <s:Label x="577" y="64" text="заказать" fontSize="16" color="white" useHandCursor="true" buttonMode="true" mouseOver="A1.source=RedImage"  mouseOut="A1.source=OkButtImage" click="image1_clickHandler(event)" />
 128:          <s:Label x="50" y="10" text="Дата вылета"/>
 129:          <s:Label x="50" y="60" text="Дата вылета" height="14"/>
 130:          <s:Label x="150" y="10" text="Время вылета"/>
 131:          <s:Label x="150" y="60" text="Время вылета"/>
 132:          <s:Label x="250" y="10" text="Время прилета"/>
 133:          <s:Label x="250" y="60" text="Время прилета"/>
 134:          <s:Label x="350" y="10" text="Номер рейса"/>
 135:          <s:Label x="350" y="60" text="Номер рейса"/>
 136:          <s:Label x="450" y="10" text="Наличие мест"/>
 137:          <s:Label x="450" y="60" text="Наличие мест"/>
 138:          <s:Label x="565" y="10" text="звоните" id="lCost" fontSize="20" color="red"/>
 139:          <s:Label x="50" y="36" id="L1"/>
 140:          <s:Label x="50" y="85" id="M1"/>
 141:          <s:Label x="150" y="36" id="L2"/>
 142:          <s:Label x="150" y="85" id="M2"/>
 143:          <s:Label x="250" y="36" id="L3"/>
 144:          <s:Label x="250" y="85" id="M3"/>
 145:          <s:Label x="350" y="36" id="L4"/>
 146:          <s:Label x="350" y="85" id="M4"/>
 147:          <s:Label x="450" y="36" id="L5"/>
 148:          <s:Label x="450" y="85" id="M5"/>
 149:          <mx:Image id="Dir" x="490" y="32" width="15" height="15" />
 150:          <mx:Image id="Ret" x="490" y="82" width="15" height="15" />
 151:      </s:BorderContainer>
 152:   
 153:  </s:ItemRenderer>
 154:   

Основной элемент рендерера - это событие, обьявляемое в строке 9 - именно на него надо подписатся в DataGroup таким вот хитрым способом, как это я сделал в строке 60 контейнера.


В строке 120 приатачены функции форматирования даты, они в принципе тут для понимания работы не требуются - но вдруг кому-то понядобятся:


   1:  import spark.formatters.NumberFormatter;
   2:   
   3:  //добавить ведущие нули при преобразовании цыфры в строку
   4:  protected  function FormatLeadingZero(Num: int, width: int) : String{
   5:      var p:String = "";
   6:      var Str1:String = Num.toString();
   7:      var L:int = Str1.length;
   8:      if (width-L>0) for (var i: int = 0; i < width - L; i++){
   9:          p += '0';
  10:      }
  11:      return p+Str1;
  12:  }
  13:   
  14:  //приводит мое цифровое представление даты в представление даты во флексе (new date)
  15:  protected   function FromStrToArr(DateStr:String):Array{
  16:      var DtArr:Array= DateStr.split(".");
  17:      if (DtArr.length==3){
  18:          try{
  19:              var NF:spark.formatters.NumberFormatter = new spark.formatters.NumberFormatter();
  20:              DtArr[0] = NF.parseNumber(DtArr[0]) as int;
  21:              DtArr[1] = (NF.parseNumber(DtArr[1]) as int)-1;
  22:              DtArr[2] = NF.parseNumber(DtArr[2]) as int;
  23:              var x:Date = new Date(DtArr[2],DtArr[1],DtArr[0]);
  24:              return DtArr;
  25:          }
  26:          catch(e:Object){
  27:              //дата некорректна
  28:          }
  29:      }
  30:      //вернем текущую дату вместо мусора на входе функции
  31:      var Dt:Array = new Array;
  32:      var y:Date = new Date();
  33:      Dt.push(y.date);
  34:      Dt.push(y.month);
  35:      Dt.push(y.fullYear);
  36:      return Dt;
  37:  }
  38:   
  39:  protected var RuDay:Array = new Array("ВСК","ПНД","ВТР","СРД","ЧТВ","ПТН","СБТ");
  40:   
  41:  //форматирует текстовую дату в моем формате в дату с названием дня
  42:  protected   function FormatDayNames(MyDate:String):String{
  43:      var DT1:Array = FromStrToArr(MyDate);
  44:      var DT2:Date = new Date(DT1[2],DT1[1],DT1[0]);
  45:      var DT3:int = RuDay[DT2.day];
  46:      return RuDay[DT3] + "  " + FormatLeadingZero(DT1[0],2)+ "." + FormatLeadingZero(DT1[1]+1,2)
  47:  }


Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19
Link to this page: http://www.vb-net.com/Flex_ItemRenderer_event/index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <MAIL ME>  <ABOUT ME>  < THANKS ME>