![]() |
|
||||||||||
|
|||||
|
[+ 1.0 08.10.14]
блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
|
Вобщем, история такая у меня есть объект данных который пришел с сервера в формате JSON я его распарсил и получил объект далее передал его своему компоненту.
Цель получить визуальное представление древовидной структуры. Почти все получилось. Удается проиллюстрировать элементарные типы данных и некоторую вложенность, но уперся в такую проблему: Если объект вложен в другой объект, то не удается показать всю цепь наследования а только последнего родителя Оно и понятно в groupingCollection нет соответствующего groupingField. При попытке же создать groupingField индивидуально для ветки он включается во все ветки и выдает unefined - все разваливается. Я не очень хорошо знаком с этим компонентом и поэтому хотел бы поинтересоваться теоретически возможно ли это или мне необходимо использовать другой компонент ? <?xml version="1.0" encoding="utf-8"?> <module:Module xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:module="modules.*" height="500" width="500" > <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.collections.HierarchicalData; import utils.Logger; import mx.collections.GroupingField; import mx.collections.Grouping; import mx.collections.GroupingCollection2; [Bindable] private var arrCollection:ArrayCollection = new ArrayCollection (); [Bindable] private var _serverData:Object; [Bindable] private var hData:HierarchicalData = new HierarchicalData (); [Bindable] public var myGColl:GroupingCollection2 = new GroupingCollection2(); private var myGrp:Grouping = new Grouping(); override public function processServerData (data:Object) :void { // Logger.addObj (data); _serverData = data; //hData.source = arrCollection; hData.source = dpFlat; myGColl.source = dpFlat; } private function parseObj ( obj:Object, rootNode:String, parentNode:String = "data") :void { var keyStr:String; var valueStr:String; for (keyStr in obj) { var newItem:Object = new Object (); if (obj[keyStr] is String || obj[keyStr] is int || obj[keyStr] is Boolean || obj[keyStr] is Number) { newItem["Value"] = String (obj[keyStr]); newItem["Type"] = typeof obj[keyStr]; newItem["Root"] = rootNode; newItem["Parent"] = parentNode; newItem["Property"] = keyStr; arrCollection.addItem (newItem); } else { if (obj[keyStr] is Array) { var arrObj:Object = new Object (); for (var i:int = 0; i < obj[keyStr].length; i++) { arrObj[i] = obj[keyStr][i] } obj[keyStr] = arrObj; } parseObj (obj[keyStr], rootNode, keyStr); } } } override public function showContent () :void { myGrp.fields = [ new GroupingField("Root"), new GroupingField("Parent")]; parseObj (_serverData, "data"); myGColl.source = arrCollection; // The Grouping instance defines the grouping fields // in the collection, and the order of the groups // in the hierarchy. // The grouping property contains a Grouping instance. myGColl.grouping = myGrp; // Refresh the display. myGColl.refresh(); this.x = Math.round ( ( Const.SCREEN_WIDTH - advancedDataGrid.width ) / 2 ); this.y = Math.round ( ( Const.SCREEN_HEIGHT - advancedDataGrid.height ) / 2 ); } ]]> </mx:Script> <!--mx:AdvancedDataGrid width="400" height="1" dataProvider= "{arrCollection}" --> <mx:AdvancedDataGrid id="advancedDataGrid" width="100%" height="100%" dataProvider="{myGColl}" initialize="arrCollection.refresh()"> <!--mx:dataProvider> <mx:HierarchicalData id = "hierarchicalData" source= "{arrCollection}" /> <mx:GroupingCollection2 id="gc" source="{arrCollection}"> <mx:Grouping> <mx:GroupingField name="Data"/> <mx:GroupingField name="Doping"/> </mx:Grouping> </mx:GroupingCollection2> </mx:dataProvider--> <mx:columns> <mx:AdvancedDataGridColumn headerText="Server data Tree" width="200" dataField="Data"/> <mx:AdvancedDataGridColumn dataField="Property" width= "160" /> <mx:AdvancedDataGridColumn dataField="Value" width="350" /> <mx:AdvancedDataGridColumn dataField="Type" width="100" /> </mx:columns> <!--mx:columns> <mx:AdvancedDataGridColumn headerText="Server data Tree" width="200" dataField="Region"/> <mx:AdvancedDataGridColumn dataField="Territory"/> <mx:AdvancedDataGridColumn dataField="Territory_Rep"/> <mx:AdvancedDataGridColumn dataField="Actual"/> <mx:AdvancedDataGridColumn dataField="Estimate"/> </mx:columns--> </mx:AdvancedDataGrid> </module:Module> |
|
|||||
|
.
|
Наследование - термин ООП. К древовидным структурам он имеет отношение как класс к объекту. Как ж. к п.
|
|
|||||
|
Регистрация: Jul 2008
Адрес: Украина, Киев
Сообщений: 253
|
для отображения древовидных структур лучше воспользоваться компонентом Tree. Если данные при парсинге выстраиваются в виде дерева, то "корешок" этого дерева можно смело добавить, например, в ArrayCollection и скормить его в Tree.dataProvider. Возможно придется заменить DefaultDataDescriptor своим собственным, чтобы дерево "понимало", исходя из каких свойств определять, есть ли у узла дочерние узлы и т.д.
|
|
|||||
|
Регистрация: Jan 2010
Сообщений: 211
|
А почему не организовать классы типа POJO и не выстраивать зависимость через них: создал конструктором объект, добавил его родителю. И удобно добавлять - все структуризированно, и управлять, так как каждому классу можно задать свою функциональность, да и структуре будет проще.
Конечно, идеальный вариант - передавать сериализованный объект, но я так понимаю, это не реализовано и не планируется. |
|
|||||
|
[+ 1.0 08.10.14]
блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
|
Уважаемое сообщество все получилось реализовать через HierarchicalData !!
<?xml version="1.0" encoding="utf-8"?> <module:Module xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:module="modules.*" height="70%" width="70%" > <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.collections.HierarchicalData; import utils.Logger; [Bindable] private var _serverData:Object; [Bindable] private var hData:HierarchicalData = new HierarchicalData (); [Bindable] private var sData:ArrayCollection; override public function processServerData (data:Object) :void { _serverData = data; var arr:Array = parseObject (_serverData); sData = new ArrayCollection (arr); sData.refresh (); hData.source = sData; hData.childrenField = "objectChildren"; } private function parseObject (object:Object) :Array { var arr:Array = []; var keyStr:String; var valueStr:String; for (keyStr in object) { var newItem:Object = new Object (); newItem["Type"] = typeof object[keyStr]; newItem["Data"] = keyStr; if (object[keyStr] is String || object[keyStr] is int || object[keyStr] is Boolean || object[keyStr] is Number) { newItem["Value"] = String (object[keyStr]); } else { newItem["objectChildren"] = parseObject(object[keyStr]); } arr.push(newItem); } return arr; } override public function showContent () :void { this.x = Math.round ( ( Const.SCREEN_WIDTH - advancedDataGrid.width ) / 2 ); this.y = Math.round ( ( Const.SCREEN_HEIGHT - advancedDataGrid.height ) / 2 ); } ]]> </mx:Script> <mx:AdvancedDataGrid id="advancedDataGrid" width="100%" height="100%" dataProvider="{hData}"> <mx:columns> <mx:AdvancedDataGridColumn headerText="Server data Tree" width="200" dataField="Data"/> <mx:AdvancedDataGridColumn dataField="Value" width="420" /> <mx:AdvancedDataGridColumn dataField="Type" width="100" /> </mx:columns> </mx:AdvancedDataGrid> </module:Module> В processServerData передается многоуровневый объект Добавлено через 9 часов 36 минут На всякий случай поясню что происходит на одном конкретном примере: 1. С сервера приходит строка в виде: {"id":"show_dopings","dopings":[{"name":"cool doping 2","id":2,"price":10, "imageUrl":"http:\/\/game.ugangz.ru\/resource\/equip\/1162.png", "description":"\u043e\u0447 \u043a\u0440\u0443\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"}, {"name":"cool doping 1", "id":1, "price":10,"imageUrl":"http:\/\/game.ugangz.ru\/resource\/equip\/1162.png", "description":"\u043e\u0447 \u043a\u0440\u0443\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"}, {"name":"cool doping 3","id":3, "price":10,"imageUrl":"http:\/\/game.ugangz.ru\/resource\/equip\/1162.png", "description":"\u043e\u0447 \u043a\u0440\u0443\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"}, {"name":"cool doping 4","id":4, "price":10,"imageUrl":"http:\/\/game.ugangz.ru\/resource\/equip\/1162.png", "description":"\u043e\u0447 \u043a\u0440\u0443\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"}, {"name":"cool doping 5","id":5,"price":10, "imageUrl":"http:\/\/game.ugangz.ru\/resource\/equip\/1162.png", "description":"\u043e\u0447 \u043a\u0440\u0443\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"}], "charDopings":{"1":1,"4":2,"3":2,"2":1} import com.adobe.serialization.json.JSON; public static function parseData( data:String ):Object { return JSON.decode( data ); } Type: Object id: show_dopings dopings: [Array] (5 elements) · 0: [Object] · · name: cool doping 2 · · id: 2 · · price: 10 · · imageUrl: http://game.ugangz.ru/resource/equip/1162.png · · description: оч крутое описание · 1: [Object] · · name: cool doping 1 · · id: 1 · · price: 10 · · imageUrl: http://game.ugangz.ru/resource/equip/1162.png · · description: оч крутое описание · 2: [Object] · · name: cool doping 3 · · id: 3 · · price: 10 · · imageUrl: http://game.ugangz.ru/resource/equip/1162.png · · description: оч крутое описание · 3: [Object] · · name: cool doping 4 · · id: 4 · · price: 10 · · imageUrl: http://game.ugangz.ru/resource/equip/1162.png · · description: оч крутое описание · 4: [Object] · · name: cool doping 5 · · id: 5 · · price: 10 · · imageUrl: http://game.ugangz.ru/resource/equip/1162.png · · description: оч крутое описание charDopings: [Object] · 1: 1 · 2: 1 · 3: 2 · 4: 2 3. Мой объект Коннектор сделал свою работу. Через собственное событие он передает наш объект получателю - в моем случае ModuleController - у Теперь модуль контролер будет определять какой тип модуля создавать на основании полученного id (внутри объекта) Но это нас сейчас не интересует. Независимо от типа модуля я хочу чтобы мое приложение могло в режиме data mode отображать полученные данные с сервера. Для этого создается специальный mxml DataGridModule 4. Все модули имеют несколько обязательных методов. О всех писать не стану, важно что наш модуль должен переопределить два метода: - processServerData (метод обработки полученных данных) - showContent (метод отображения данных - вызывается всегда после flex события creationComplete) 5. Теперь самое интересное ! ... Добавлено через 10 часов 10 минут 5 ... Для отображения иерархической структуры данных я выбрал объект AdvancedDataGrid уж очень захотелось поработать с этим модным компонентом. Хотя более очевидным решением было бы сделать через mx.controls.Tree Возможно если вы работаете во FlashDevelop у вас по умолчанию не обнаруживается соответствующего компонента, поскольку adobe хотела подзаработать на нем. В общем не знаю насколько это законно. Но если это не законно - то не в коем случае не делайте так http://www.actionscriptdeveloper.co....-flashdevelop/ 6. создаем наш advancedDataGrid <mx:AdvancedDataGrid id="advancedDataGrid" width="100%" height="100%" dataProvider="{hData}"> <mx:columns> <mx:AdvancedDataGridColumn headerText="Server data Tree" width="200" dataField="Data"/> <mx:AdvancedDataGridColumn dataField="Value" width="420" /> <mx:AdvancedDataGridColumn dataField="Type" width="100" /> </mx:columns> </mx:AdvancedDataGrid> но мне сейчас это не нужно в моем случае я заранее знаю что хочу отобразить, а именно: слева иерархию объектов - справа две колонки : значение свойства объекта, тип свойства. Теперь самая чувствительная часть - dataProvider. Во flex dataProvider как оказалось понятие достаточно растяжимое. Поскольку я едва едва освоился во flex, что я только не пихал в качестве объекта dataProvider - в том числе и датаПровайдер из компонентов CS3 fl.data.* В конце концов я добрался до ArrayCollection. Короче это все лирические отступления. Мне помогло вот это: http://livedocs.adobe.com/flex/3/htm...tagrid_06.html И вот это : http://livedocs.adobe.com/flex/3/htm...tagrid_07.html Я понял как должен выглядеть мой исходный объект и за счет чего HierarchicalData сможет мне его отобразить (за счет свойства childrenField): Теперь осталось сделать съедобным наш серверный объект и скормить его объекту arrayCollection. Этим целям служит рекурсивная функция parseObject private function parseObject (object:Object) :Array { var arr:Array = []; var keyStr:String; var valueStr:String; for (keyStr in object) { var newItem:Object = new Object (); newItem["Type"] = typeof object[keyStr]; newItem["Data"] = keyStr; if (object[keyStr] is String || object[keyStr] is int || object[keyStr] is Boolean || object[keyStr] is Number) { newItem["Value"] = String (object[keyStr]); } else { newItem["objectChildren"] = parseObject(object[keyStr]); } arr.push(newItem); } return arr; } Последний раз редактировалось inozemcev; 13.06.2010 в 13:20. |
![]() |
![]() |
Часовой пояс GMT +4, время: 11:16. |
|
|
« Предыдущая тема | Следующая тема » |
| Теги |
| advanceddatagrid |
|
|