/// <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); } }
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); } }