private PivotMemberItem AddRowMember(List<PivotMemberItem> container, MemberInfo member, int columnIndex, int rowIndex, out int memberSize, int drillDepth)
        {
            // Добавляем в случае необходимости строку и столбец
            ColumnsCount = Math.Max(ColumnsCount, columnIndex + 1);
            RowsCount = Math.Max(RowsCount, rowIndex + 1);
            
            // Сохраняем максимальной глубины DrillDown
            if (m_DrillDepth.ContainsKey(columnIndex))
                m_DrillDepth[columnIndex] = Math.Max(m_DrillDepth[columnIndex], drillDepth);
            else
                m_DrillDepth[columnIndex] = drillDepth;

            // Элемент сводной таблицы
            PivotMemberItem item = new PivotMemberItem(member);
            item.PivotDrillDepth = drillDepth;
            item.ColumnIndex = columnIndex;
            item.RowIndex = rowIndex;

            container.Add(item);

            // Дочерние элементы начинаются отображаться с той же строки. только в соседней колонке
            // Номер строки с которой начнется отображение элемента
            int start_Child_RowIndex = rowIndex;
            // Текущий индекс строки
            int current_Child_RowIndex = start_Child_RowIndex;
            // Размер добавляемого контрола (в строках)
            int size = 0;
            foreach (MemberInfo child in member.Children)
            {
                AddRowMember(item.Children, child, columnIndex + 1, current_Child_RowIndex, out size, 0);
                current_Child_RowIndex += size;
            }
            // Номер строки, на которой закончится отображение элемента
            int end_Child_RowIndex = current_Child_RowIndex;
            int ChildrenSize = end_Child_RowIndex - start_Child_RowIndex;

            // Дрилл-даун дочерние отображаются в этой же колонке, но со строки следующей после самого элемента и всех дочерних
            // Номер строки с которой начнется отображение элемента
            int start_DrillDown_RowIndex = ChildrenSize > 0 ? end_Child_RowIndex : rowIndex + 1;
            // Текущий индекс строки
            int current_DrillDown_RowIndex = start_DrillDown_RowIndex;

            // Размер добавляемого контрола (в строках)
            size = 0;
            int i = 0;
            foreach (MemberInfo child in member.DrilledDownChildren)
            {
                PivotMemberItem dd_item = AddRowMember(item.DrillDownChildren, child, columnIndex, current_DrillDown_RowIndex, out size, drillDepth + 1);
                if (i == 0)
                    dd_item.IsFirstDrillDownChild = true;
                i++;
                current_DrillDown_RowIndex += size;
            }
            // Номер строки, на которой закончится отображение элемента
            int end_DrillDown_RowIndex = current_DrillDown_RowIndex;
            int DrillDownChildrenSize = end_DrillDown_RowIndex - start_DrillDown_RowIndex;

            // Растягиваем элемент если есть дочерние
            int span_Size = 1;
            int span_Size_WithChildren = 1;
            if (ChildrenSize > 1)
            {
                span_Size_WithChildren = ChildrenSize;
            }
            if (DrillDownChildrenSize > 0)
            {
                span_Size = span_Size_WithChildren + DrillDownChildrenSize;
            }
            else
            {
                span_Size = span_Size_WithChildren;
            }

            if (span_Size > 1)
            {
                item.RowSpan = span_Size;
            }

            item.ChildrenSize = ChildrenSize;
            item.DrillDownChildrenSize = DrillDownChildrenSize;
            memberSize = span_Size;
            return item;
        }
 public MemberLayoutItem(PivotMemberItem pivotMember)
 {
     PivotMember = pivotMember;
 }
        private PivotMemberItem AddRowMember(List <PivotMemberItem> container, MemberInfo member, int columnIndex, int rowIndex, out int memberSize, int drillDepth)
        {
            // Добавляем в случае необходимости строку и столбец
            ColumnsCount = Math.Max(ColumnsCount, columnIndex + 1);
            RowsCount    = Math.Max(RowsCount, rowIndex + 1);

            // Сохраняем максимальной глубины DrillDown
            if (m_DrillDepth.ContainsKey(columnIndex))
            {
                m_DrillDepth[columnIndex] = Math.Max(m_DrillDepth[columnIndex], drillDepth);
            }
            else
            {
                m_DrillDepth[columnIndex] = drillDepth;
            }

            // Элемент сводной таблицы
            PivotMemberItem item = new PivotMemberItem(member);

            item.PivotDrillDepth = drillDepth;
            item.ColumnIndex     = columnIndex;
            item.RowIndex        = rowIndex;

            container.Add(item);

            // Дочерние элементы начинаются отображаться с той же строки. только в соседней колонке
            // Номер строки с которой начнется отображение элемента
            int start_Child_RowIndex = rowIndex;
            // Текущий индекс строки
            int current_Child_RowIndex = start_Child_RowIndex;
            // Размер добавляемого контрола (в строках)
            int size = 0;

            foreach (MemberInfo child in member.Children)
            {
                AddRowMember(item.Children, child, columnIndex + 1, current_Child_RowIndex, out size, 0);
                current_Child_RowIndex += size;
            }
            // Номер строки, на которой закончится отображение элемента
            int end_Child_RowIndex = current_Child_RowIndex;
            int ChildrenSize       = end_Child_RowIndex - start_Child_RowIndex;

            // Дрилл-даун дочерние отображаются в этой же колонке, но со строки следующей после самого элемента и всех дочерних
            // Номер строки с которой начнется отображение элемента
            int start_DrillDown_RowIndex = ChildrenSize > 0 ? end_Child_RowIndex : rowIndex + 1;
            // Текущий индекс строки
            int current_DrillDown_RowIndex = start_DrillDown_RowIndex;

            // Размер добавляемого контрола (в строках)
            size = 0;
            int i = 0;

            foreach (MemberInfo child in member.DrilledDownChildren)
            {
                PivotMemberItem dd_item = AddRowMember(item.DrillDownChildren, child, columnIndex, current_DrillDown_RowIndex, out size, drillDepth + 1);
                if (i == 0)
                {
                    dd_item.IsFirstDrillDownChild = true;
                }
                i++;
                current_DrillDown_RowIndex += size;
            }
            // Номер строки, на которой закончится отображение элемента
            int end_DrillDown_RowIndex = current_DrillDown_RowIndex;
            int DrillDownChildrenSize  = end_DrillDown_RowIndex - start_DrillDown_RowIndex;

            // Растягиваем элемент если есть дочерние
            int span_Size = 1;
            int span_Size_WithChildren = 1;

            if (ChildrenSize > 1)
            {
                span_Size_WithChildren = ChildrenSize;
            }
            if (DrillDownChildrenSize > 0)
            {
                span_Size = span_Size_WithChildren + DrillDownChildrenSize;
            }
            else
            {
                span_Size = span_Size_WithChildren;
            }

            if (span_Size > 1)
            {
                item.RowSpan = span_Size;
            }

            item.ChildrenSize          = ChildrenSize;
            item.DrillDownChildrenSize = DrillDownChildrenSize;
            memberSize = span_Size;
            return(item);
        }
        void AddToColumnsLayout(PivotMemberItem member)
        {
            if (member != null)
            {
                // Для данного элемента пытаемся получить по координатам LayoutCellWrapper
                LayoutCellWrapper itemWrapper = ColumnsLayout[member.ColumnIndex, member.RowIndex];
                if (itemWrapper == null)
                {
                    itemWrapper = new LayoutCellWrapper();
                    ColumnsLayout.Add(itemWrapper, member.ColumnIndex, member.RowIndex);
                }

                // Создаем описатель для данного элемента и добавляем его в коллекцию объектов ячейки сетки
                MemberLayoutItem item = new MemberLayoutItem(member);
                itemWrapper.Items.Add(item);
                item.RowSpan = member.RowSpan;
                item.ColumnSpan = member.ColumnSpan;

                // Если элемент в ширину больше чем 1, то добавляем фиктивные элементы на сетку
                for (int i = 1; i < member.ColumnSpan; i++)
                {
                    LayoutCellWrapper ext_itemWrapper = ColumnsLayout[member.ColumnIndex + i, member.RowIndex];
                    if (ext_itemWrapper == null)
                    {
                        ext_itemWrapper = new LayoutCellWrapper();
                        ColumnsLayout.Add(ext_itemWrapper, member.ColumnIndex + i, member.RowIndex);
                    }

                    // Создаем описатель для фиктивного элемента
                    MemberLayoutItem ext_item = new MemberLayoutItem(member);
                    ext_item.IsExtension = true;
                    ext_itemWrapper.Items.Add(ext_item);
                    ext_item.ColumnSpan = member.ColumnSpan - i;
                    ext_item.RowSpan = member.RowSpan;
                }

                foreach (PivotMemberItem dd_item in member.DrillDownChildren)
                {
                    AddToColumnsLayout(dd_item);
                }
                foreach (PivotMemberItem child_item in member.Children)
                {
                    AddToColumnsLayout(child_item);
                }
            }
        }
 public MemberLayoutItem(PivotMemberItem pivotMember)
 {
     if (pivotMember == null)
         throw new ArgumentNullException("pivotMember");
     PivotMember = pivotMember;
 }