/// <summary>
            /// Gets the parent of the requested node,
            /// and deletes the indicated child iteration.
            /// </summary>
            /// <include file="../Shared/Help.xml" path="Help/intAry/param[@name='rptIdx']"/>
            public override void DeleteIteration(int[] rptIdx)
            {
                // get the parent of the requested node,
                // and delete the indicated child iteration
                int iterationToDelete;

                int[] parIdx = TrimIndices(IndexTrimOptions.TruncateLastIndex, out iterationToDelete, rptIdx);
                if (iterationToDelete < 0)                 // there is no iteration to be deleted!
                {
                    return;
                }

                ValueNode <T> parentNode = GetNode(GetNodeOptions.NoBubbleAndFlow, parIdx);

                if (parentNode == null || parentNode.Children == null || iterationToDelete >= parentNode.Children.SetCount)
                {
                    return;
                }

                parentNode.Children.RemoveAt(iterationToDelete);

                if (AnswerCollection != null)
                {
                    AnswerCollection.OnAnswerChanged(this, rptIdx, ValueChangeType.IndexShift);
                }
            }
            /// <summary>
            /// Gets the parent of the requested node,
            /// and inserts an unanswered child iteration at the requested index.
            /// </summary>
            /// <include file="../Shared/Help.xml" path="Help/intAry/param[@name='rptIdx']"/>
            public override void InsertIteration(int[] rptIdx)
            {
                // get the parent of the requested node,
                // and insert an unanswered child iteration at the requested index
                int iterationToInsert;

                int[] parIdx = TrimIndices(IndexTrimOptions.TruncateLastIndex, out iterationToInsert, rptIdx);
                if (iterationToInsert < 0)                 // there is no iteration before which to insert!
                {
                    return;
                }

                ValueNode <T> parentNode = GetNode(GetNodeOptions.NoBubbleAndFlow, parIdx);

                if (parentNode == null || parentNode.Children == null || iterationToInsert >= parentNode.Children.SetCount)
                {
                    return;
                }

                parentNode.Children.Insert(iterationToInsert, new ValueNode <T>());
                if (AnswerCollection != null)
                {
                    AnswerCollection.OnAnswerChanged(this, rptIdx, ValueChangeType.IndexShift);
                }
            }
Пример #3
0
        protected void SetValue <T>(T value, bool suppressChangeNotification, params int[] rptIdx) where T : IValue
        {
            // The first parameter to GetValueNode (below) determines whether it will create nodes as necessary
            // to get to the requested index.  We only bother to expand the tree if the value we're setting
            // is answered.
            bool          nodeCreatedForUnansweredValue = false;
            ValueNode <T> node = GetValueNode <T>(value.IsAnswered, rptIdx);

            // if we're setting a value that's answered, GetValueNode should always be returning something!
            // (When we set things to unanswered, the tree won't be expanding to hold the value, so we may get null back.)

            if (node == null)
            {
                // we're setting an unanswered value into the answer collection.
                // In this case we still need to expand the tree to have a place representing that unanswered value.
                node = GetValueNode <T>(true, rptIdx);
                nodeCreatedForUnansweredValue = true;
            }

            Debug.Assert(node != null);
            if (node != null)
            {
                ValueChangeType changed;
                if (value.IsAnswered && !node.Value.IsAnswered)
                {
                    changed = ValueChangeType.BecameAnswered;
                }
                else if (!value.IsAnswered && node.Value.IsAnswered)
                {
                    changed = ValueChangeType.BecameUnanswered;
                }
                else if (value.IsAnswered && node.Value.IsAnswered && !value.Equals(node.Value))
                {
                    changed = ValueChangeType.Changed;
                }
                else
                {
                    changed = ValueChangeType.None;
                }

                node.Value = value;

                if (changed != ValueChangeType.None || nodeCreatedForUnansweredValue)
                {
                    // if we have un-answered a repeated variable; perform any value tree cleanup that is needed
                    if (rptIdx != null && rptIdx.Length > 0 && !value.IsAnswered)
                    {
                        Recalculate(rptIdx);
                    }

                    if (changed != ValueChangeType.None && _coll != null && !suppressChangeNotification)
                    {
                        _coll.OnAnswerChanged(this, rptIdx, changed);
                    }
                }
            }
        }
            /// <summary>
            /// Gets the parent of the requested node, and removes the indicated child iteration from the parent, and re-inserts it at the indicated new position.
            /// </summary>
            /// <include file="../Shared/Help.xml" path="Help/intAry/param[@name='rptIdx']"/>
            /// <param name="newPosition">newPosition</param>
            public override void MoveIteration(int[] rptIdx, int newPosition)
            {
                if (newPosition < 0)
                {
                    throw new ArgumentException("Cannot move repeated data before the first repeat iteration.", "newPosition");
                }
                // get the parent of the requested node,
                // removes the indicated child iteration from the parent,
                // and re-inserts it at the indicated new position
                int iterationToMove;

                int[] parIdx = TrimIndices(IndexTrimOptions.TruncateLastIndex, out iterationToMove, rptIdx);
                if (iterationToMove < 0)                 // there is no iteration to be moved!
                {
                    return;
                }

                ValueNode <T> parentNode = GetNode(GetNodeOptions.NoBubbleAndFlow, parIdx);

                if (parentNode == null || parentNode.Children == null ||
                    (newPosition < iterationToMove && newPosition >= parentNode.Children.SetCount) ||                     // move up
                    (newPosition > iterationToMove && iterationToMove >= parentNode.Children.SetCount))                        // move down
                {
                    // nothing to do
                    return;
                }

                int maxIteration = Math.Max(iterationToMove, newPosition);

                if (maxIteration >= parentNode.Children.SetCount)
                {
                    //[LRS] Need to be able to do the following! (Because other answers in same iteration may be moving.)
                    //throw new ArgumentException("Cannot move repeated data after the final repeat iteration.", "newPosition");
                    parentNode.Children.PrepareForIndex(maxIteration);
                }

                ValueNode <T> movedNode = parentNode.Children.RemoveAt(iterationToMove);

                parentNode.Children.Insert(newPosition, movedNode);
                if (AnswerCollection != null)
                {
                    AnswerCollection.OnAnswerChanged(this, rptIdx, ValueChangeType.IndexShift);
                }
            }