/// <summary>
 ///     Compare two VirtualTreeStartDragData structures
 /// </summary>
 /// <param name="operand1">Left operand</param>
 /// <param name="operand2">Right operand</param>
 /// <returns>true if operands are equal</returns>
 public static bool Compare(VirtualTreeStartDragData operand1, VirtualTreeStartDragData operand2)
 {
     return operand1.myData == operand2.myData && operand1.myAllowedEffects == operand2.myAllowedEffects;
 }
 /// <summary>
 ///     Compare two VirtualTreeStartDragData structures
 /// </summary>
 /// <param name="operand1">Left operand</param>
 /// <param name="operand2">Right operand</param>
 /// <returns>true if operands are equal</returns>
 public static bool Compare(VirtualTreeStartDragData operand1, VirtualTreeStartDragData operand2)
 {
     return(operand1.myData == operand2.myData && operand1.myAllowedEffects == operand2.myAllowedEffects);
 }
        /// <summary>
        ///     Package a drag object to use with DoDragDrop or Copy/Paste operations. Use the passed in location
        ///     for a single select tree, and the current selection state for a multiselect tree. Derived
        ///     classes can override this function to add extra information to the returned drag data. Any override
        ///     should first defer to the base implementation.
        /// </summary>
        /// <param name="row">Target row in the tree</param>
        /// <param name="nativeColumn">The native column</param>
        /// <param name="dragReason">The reason for retrieving the drop object</param>
        /// <returns>A populated drag structure. IsEmpty may be true.</returns>
        protected virtual VirtualTreeStartDragData PopulateDragData(int row, int nativeColumn, DragReason dragReason)
        {
            ClearDragSources();
            if (GetStyleFlag(VTCStyleFlags.MultiSelect))
            {
                var iter = CreateSelectedItemEnumerator();
                if (iter != null)
                {
                    var finished = false;
                    try
                    {
                        List<VirtualTreeStartDragData> sourceData = null;
                        var firstDragData = new VirtualTreeStartDragData();
                        var intersectEffects = GetStateFlag(VTCStateFlags.CombineDragEffectsWithAnd);
                        var allowedEffects = DragDropEffects.None;
                        var totalCount = 0;
                        while (iter.MoveNext())
                        {
                            var dragData = iter.Branch.OnStartDrag(this, iter.RowInBranch, iter.ColumnInBranch, dragReason);
                            if (dragReason == DragReason.CanCut
                                || dragReason == DragReason.CanCopy)
                            {
                                // special handling for cut/copy queries.
                                if (dragData == VirtualTreeStartDragData.AllowCutCopy)
                                {
                                    firstDragData = dragData;
                                    totalCount = 1;
                                }
                                else
                                {
                                    // bail out, operation is not supported
                                    finished = true;
                                    return VirtualTreeStartDragData.Empty;
                                }
                            }
                            else if (!dragData.IsEmpty)
                            {
                                if (totalCount == 0)
                                {
                                    // Store the first one without using the lists, we return it directly in this case
                                    mySingleDragSource = new DragSourceOwner(iter.Branch, iter.RowInBranch, iter.ColumnInBranch);
                                    firstDragData = dragData;
                                    allowedEffects = dragData.AllowedEffects;
                                    ++totalCount;
                                }
                                else
                                {
                                    if (totalCount == 1)
                                    {
                                        // We're moving from a single item to multiple items.
                                        // Move our single drag data and source information into
                                        // lists.
                                        sourceData = new List<VirtualTreeStartDragData>();
                                        sourceData.Add(firstDragData);
                                        if (myDragSources == null)
                                        {
                                            myDragSources = new List<DragSourceOwner>();
                                        }
                                        myDragSources.Add(mySingleDragSource);
                                        mySingleDragSource.Clear();
                                    }

                                    // Add source owners before the potential cancel coming from intersectAffects
                                    myDragSources.Add(new DragSourceOwner(iter.Branch, iter.RowInBranch, iter.ColumnInBranch));
                                    if (intersectEffects)
                                    {
                                        allowedEffects &= dragData.AllowedEffects;
                                        if (allowedEffects == 0)
                                        {
                                            // The finaly clause will clear out the data sources gracefully
                                            // if we don't set the finished signal.
                                            return VirtualTreeStartDragData.Empty;
                                        }
                                    }
                                    else
                                    {
                                        allowedEffects |= dragData.AllowedEffects;
                                    }
                                    sourceData.Add(dragData);
                                    ++totalCount;
                                }
                            }
                        }
                        finished = true;
                        if (totalCount == 1)
                        {
                            return firstDragData;
                        }
                        else if (totalCount > 1)
                        {
                            // Keep this CLS compliant and just return the array of structures
                            // as returned by the branches.
                            return new VirtualTreeStartDragData(sourceData.ToArray(), allowedEffects);
                        }
                    }
                    finally
                    {
                        if (!finished)
                        {
                            ForceCancelDataSources();
                        }
                    }
                }
            }
            else
            {
                var info = myTree.GetItemInfo(row, nativeColumn, false);
                var dragData = info.Branch.OnStartDrag(this, info.Row, info.Column, dragReason);
                if (!dragData.IsEmpty)
                {
                    mySingleDragSource = new DragSourceOwner(info.Branch, info.Row, info.Column);
                    return dragData;
                }
            }
            return VirtualTreeStartDragData.Empty;
        }