Как остановить AdvancedDataGrid с HierarchicalData от перемещения дочерних элементов с несколькими родителями на разные уровни?

У меня проблема с тем, что мой дочерний элемент перемещается вместе с самим собой в диаграмме, где у него несколько родителей на разных уровнях. Это немного странно, и я думаю, что это может быть предназначенная функциональность, чтобы показать, что это тот же элемент, но он выглядит в моих сетках данных и иногда отсоединяется от сетки!

РЕДАКТИРОВАТЬ: я знаю, что это потому, что я использую один и тот же объект, но я хочу использовать один и тот же объект в обоих местах, так что, когда я нажимаю один из них, я получаю один и тот же dg.selectedItem. Я ищу способ предотвратить движение дерева внутри обоих объектов вместо одного (ЕСЛИ ВОЗМОЖНО), а не использовать разные объекты.

Я упростил его до этого кода, чтобы проиллюстрировать проблему:

<?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:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            [Bindable] var ac:ArrayCollection;

            public function init():void
            {
                ac = new ArrayCollection();
                var objWithMultipleParents:Object = {name:"Awkward family tree"};
                ac.addItem({
                    name:"Parent 1",
                    children:[
                        objWithMultipleParents,
                        {name:"Child of Parent 1"}  
                    ]
                });
                ac.addItem({
                    name:"Parent 2",
                    children:[
                        {name:"Child of Parent 2",children:[objWithMultipleParents]},
                        {name:"Child #2 of Parent 2"}
                    ]
                });
            }

        ]]>
    </fx:Script>

    <mx:AdvancedDataGrid id="dg" width="100%" height="100%">
        <mx:dataProvider>
            <mx:HierarchicalData source="{ac}" />
        </mx:dataProvider>
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="name" headerText="Groups"/>
        </mx:columns>
    </mx:AdvancedDataGrid>
</s:Application>

Перед расширением ребенка 1 от родителя 2:

Перед расширением Ребенка 1 из Родителя 2

После расширения ребенка 1 от родителя 2:

После расширения Ребенка 1 из Родителя 2

Есть ли способ предотвратить это?

3 ответа

Решение

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

//store item reference in accessible object
obj = new Object();
obj[itemRef.uid] = itemRef;

//copy enough information to display and re-access correctly
copy1.name = itemRef.name;
copy1.uid = itemRef.uid;
parent1.add(copy1);

copy2.name = itemRef.name;
copy2.uid = itemRef.uid;
parent2.add(copy2);

//on item selection, access it through uid
itemRef = obj[dg.selectedItem.uid];

Если у вас нет какого-либо UID и вы не хотите его создавать, вы также можете использовать простые копии в качестве ключей элементов.

//make copies
copy1.name = itemRef.name;
copy2.name = itemRef.name;
parent1.add(copy1);
parent2.add(copy2);

//map references
obj[copy1] = itemRef;
obj[copy2] = itemRef;

//re-access
itemRef = obj[dg.selectedItem];

Любой узел в дереве может появиться только один раз в дереве. Период. Ссылка (obnject ID) узла идентифицирует место, где он находится в дереве. Многократное его добавление разрушит все механизмы, которые должны знать, где в дереве находится узел. Только противоположный способ будет работать (зная, какой узел находится в определенной позиции). Одним из побочных эффектов является неправильный отступ. Когда показан дочерний элемент узла, требуемый отступ рассчитывается и применяется к его внешнему виду - при всех вхождениях в дереве, независимо от того, находятся ли они на совершенно другом уровне отступа.

Если вам нужно представить одни и те же данные в разных местах, сделайте ваши узлы дерева просто обертками для объекта, который содержит данные. Дерева дерева являются независимыми объектами, но извлекают их имя, значок, всплывающую подсказку, независимо от того, на какой объект они ссылаются. И на этот "объект данных" может ссылаться любое количество узлов дерева. Даже когда вам нужно узнать, по каким данным щелкнули, вы можете взять ссылку на узел дерева из сообщения и извлечь из него ссылку на объект данных для дальнейшей обработки.

Итак, вот ваша проблема.

var objWithMultipleParents:Object = {name:"Problem"};

Вы создаете один объект и используете его в нескольких местах.
В AS3 объекты передаются по ссылке.
С учетом сказанного, если вы изменяете объект в одном элементе, вы меняете его во "всех".
Обратите внимание, что в моем примере я использую функцию для создания нового объекта вместо того, чтобы ссылаться на один и тот же объект снова и снова.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    minWidth="955" minHeight="600"
               creationComplete="init()">
<mx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;

        [Bindable]
        public var ac:ArrayCollection;

        public function init():void
        {
            ac = new ArrayCollection();
            var objWithMultipleParents:Object = createObject( );
            ac.addItem({
                name:"Parent 1",
                children:[
                    objWithMultipleParents,
                    {name:"Child of Parent 1"}  
                ]
            });
            ac.addItem({
                name:"Parent 2",
                children:[
                    {name:"Child of Parent 2",children:[createObject( )]},
                    {name:"Child #2 of Parent 2"}
                ]
            });
        }
        public function createObject( ):Object{
            return {name:"Problem"}
        }

    ]]>
</mx:Script>

<mx:AdvancedDataGrid id="dg" width="100%" height="100%">
    <mx:dataProvider>
        <mx:HierarchicalData source="{ac}" />
    </mx:dataProvider>
    <mx:columns>
        <mx:AdvancedDataGridColumn dataField="name" headerText="Groups"/>
    </mx:columns>
</mx:AdvancedDataGrid>

Также вы можете посмотреть в HierarchicalData

Другие вопросы по тегам