Лучший способ установить выбор гибкого элемента управления, который еще не инициализирован - PullRequest
1 голос
/ 26 марта 2009

Чтобы проиллюстрировать вопрос, я действительно упрощу пример (на самом деле код гораздо более запутанный).

Скажем, у вас есть гибкий элемент управления, который содержит сетку данных. Что-то вроде

<mx:DataGrid id="grid" dataProvider="{document.items}">
    <mx:columns>
        <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
        <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
    </mx:columns>
</mx:DataGrid>

Где документ - это объект Model, содержащий некоторые данные. Вы предоставляете установщик выбора в элементе управления, так как клиенты не хотят ничего знать о базовой модели данных:

public function set selectedItem(title:String):Allocation
{
   grid.selectedItem  = null;

   for each(var o:Object in grid.dataProvider)
   {
      var t:String = o.@title;
      if( t == title )
      {
         grid.selectedItem = o;
         return;
      }
   }
}

Пока все хорошо. При условии, что document.items предварительно заполнен, выбор будет работать правильно. Тем не мение. Что делать, если вы уже знаете, при запуске приложения, каким должен быть выбор - он был передан (например) в URL? Так что в flex вы можете иметь что-то вроде

// Initialising now...
mycontrol.document = this.document; // give the control the document

// Fetch titles
new FetchTitlesEvent().dispatch(); // cairngorm-style event

// Set the selection 
mycontrol.selectedItem = Application.application.parameters.title;

OOps . Поскольку FetchTitlesEvent работает асинхронно, в то время как mycontrol.selectedItem не может работать. Каким-то образом нам нужно (повторно) запустить этот код, чтобы установить выбор в элементе управления. Теперь есть несколько способов сделать это, но у всех есть запахи кода:

1) Сделайте это в FetchTitlesCommand после завершения выборки. - Это загрязняет команду знанием представления (или представления s ), которое должно знать это. Ощущается как кошмар обслуживания, ожидающий наступления, и означает, что представления полностью связаны с командами, и эти команды не могут использоваться повторно. Blech.

2) Иметь обратный вызов от события, когда оно завершено, которое это делает (либо создайте некоторую составную команду, которая начинается в FetchTitlesEvent и заканчивается новой командой для выполнения набора). Мне кажется хрупким - как сопровождающий узнает , какие обратные вызовы необходимы? И это все еще связывает знания управления пользовательским интерфейсом в команды. Badness.

3) Имейте некоторый таймер, ожидающий, пока очередь событий не будет в течение некоторого времени. Hackity hackhack.

4) Сделайте это в контроле. Привязать к коллекции событий в mycontrol на document.items, отслеживать изменения. Как только появится строка, соответствующая выбору, выберите ее и остановите мониторинг изменений. - Контроль чувствует себя в нужном месте, чтобы сделать это - события коллекции иногда вызывают захватывающие события CHANGE или REFRESH - кажется, дорогой монитор, чтобы лежать вокруг

Я довольно сильно склоняюсь к (4). Существуют ли какие-либо другие варианты, которые использовались сгибателями прежде, чтобы перехватить эту проблему - особенно есть ли какие-либо кодифицированные в библиотеки, которые я мог бы использовать, поскольку это должно быть довольно универсальной проблемой?

Ответы [ 4 ]

2 голосов
/ 26 марта 2009

Можно установить для свойства selectedItem элемента управления переменную Bindable Object:

<mx:Script>
    <![CDATA[
        [Bindable]
        private var mySelectedItem:Object;
    ]]>
</mx:Script>

<mx:DataGrid id="grid" dataProvider="{document.items}" selectedItem="{mySelectedItem}">
    <mx:columns>
        <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
        <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
    </mx:columns>
</mx:DataGrid>

Таким образом, вы можете установить или сбросить selectedItem в любое время, и элемент управления обновит selectedItem на основе объекта. Например, вы можете установить в обработчике событие инициализации, событие creationComplete или любую другую функцию. Вам может потребоваться вызвать validateNow () для элемента управления, когда вы устанавливаете переменную, или для creationComplete элемента управления, если вы устанавливаете переменную во время инициализации.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initializeHandler();">
    <mx:Script>
        <![CDATA[
            [Bindable]
            private var mySelectedItem:Object;

            private function initializeHandler():void
            {
                mySelectedItem = getSelectedItem(); // your logic to determine the initial item to select
            }

            ....

            private function grid_creationCompleteHandler():void
            {
                grid.validateNow();
            }
        ]]>
    </mx:Script>

    <mx:DataGrid id="grid" dataProvider="{document.items}" selectedItem="{mySelectedItem}" creationComplete="grid_creationCompleteHandler();">
        <mx:columns>
            <mx:DataGridColumn headerText="Column 1" dataField="@name"/>
            <mx:DataGridColumn headerText="Column 2" dataField="@value"/>
        </mx:columns>
    </mx:DataGrid>
</mx:Application>
1 голос
/ 26 марта 2009

Правильный способ сделать это с событием creationComplete, если я правильно понимаю ваш вопрос. Все объекты пользовательского интерфейса во flex транслируют событие creationComplete, которое сообщает вам, когда все сделано и готово к работе. Вы можете прослушивать событие creationComplete в самой сетке или прослушивать его в приложении, поскольку оно не будет транслироваться до тех пор, пока не будут созданы все его дочерние элементы (то есть все).

0 голосов
/ 31 марта 2009

Попробуйте использовать ChangeWatcher

var cw:ChangeWatcher = ChangeWather.watch(this, ["document","items"], 
function(e:Event):void
{
    //check to see if the data we want to select has arrived

    //once we've selected the data, we don't need this handler anymore
    cw.unwatch();
});

Прошу прощения за любые синтаксические ошибки, у меня нет FB передо мной.

0 голосов
/ 26 марта 2009

К сожалению, это не проблема создания-завершения - проблема не в инициализации элемента управления, а в инициализации данных . Поскольку он асинхронный, вы не знаете, когда он в конце концов придет.

...