public static PerformMemberActionArgs CreatePerformMemberActionArgs(String connectionString,
     ShortMemberInfo member,
     int axisIndex,
     MemberActionType action,
     List<ShortMemberInfo> ascendants)
 {
     PerformMemberActionArgs args = new PerformMemberActionArgs();
     args.Connection = connectionString;
     args.Member = member;
     args.AxisIndex = axisIndex;
     args.Action = action;
     args.Ascendants = ascendants;
     return args;
 }
        void DrillUpMember(PerformMemberActionArgs args)
        {
            //using (WaitCursor wc = new WaitCursor())
            {
                IList<DrillActionContainer> actions = null;
                if (!RotateAxes)
                {
                    actions = args.AxisIndex == 0 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                else
                {
                    actions = args.AxisIndex == 1 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                DrillActionContainer previous = null;
                DrillActionContainer container = null;

                // Действия над элементами из этой же иерархии
                IList<DrillActionContainer> actionsToHierarchy = History.CurrentHistoryItem.FindDrillActionContainersByHierarchy(actions, args.Member.HierarchyUniqueName);
                if (actionsToHierarchy != null)
                {
                    // Все действия зануляем
                    foreach (DrillActionContainer action in actionsToHierarchy)
                    {
                        action.Action = null;
                    }
                }

                // Родители
                if (args.Ascendants != null)
                {
                    for (int i = args.Ascendants.Count - 1; i >= 0; i--)
                    {
                        ShortMemberInfo mi = args.Ascendants[i];

                        container = History.CurrentHistoryItem.FindDrillActionContainer(actions, mi.UniqueName);
                        if (container == null)
                        {
                            container = new DrillActionContainer(mi.UniqueName, mi.HierarchyUniqueName);
                            if (previous == null)
                                actions.Add(container);
                            else
                                previous.Children.Add(container);
                        }
                        previous = container;
                    }
                }

                // Сам элемент
                container = History.CurrentHistoryItem.FindDrillActionContainer(actions, args.Member.UniqueName);
                if (container == null)
                {
                    container = new DrillActionContainer(args.Member.UniqueName, args.Member.HierarchyUniqueName);
                    container.Action = new MdxDrillUpAction(args.Member.UniqueName, args.Member.HierarchyUniqueName, args.Member.LevelDepth);
                    if (previous == null)
                        actions.Add(container);
                    else
                        previous.Children.Add(container);
                }
                else
                {
                    // Удаляем все вложенные экшены для данной иерархии
                    IList<DrillActionContainer> child_actionsToHierarchy = History.CurrentHistoryItem.FindDrillActionContainersByHierarchy(container.Children, args.Member.HierarchyUniqueName);
                    if (child_actionsToHierarchy != null)
                    {
                        // Все действия зануляем
                        foreach (DrillActionContainer action in child_actionsToHierarchy)
                        {
                            action.Action = null;
                        }
                    }

                    container.Action = new MdxDrillUpAction(args.Member.UniqueName, args.Member.HierarchyUniqueName, args.Member.LevelDepth);
                }
            }
            /*using (WaitCursor wc = new WaitCursor())
            {
                IList<DrillActionContainer> actions = args.AxisIndex == 0 ? ColumnsActionChain : RowsActionChain;

                actions.Clear();

                DrillActionContainer container = new DrillActionContainer(args.Member.UniqueName);
                container.Action = new MdxDrillUpAction(args.Member.UniqueName);

                actions.Add(container);

                this.RefreshQuery();
            }*/
        }
        private void ExpandMember(PerformMemberActionArgs args)
        {
            //using (WaitCursor wc = new WaitCursor())
            {
                IList<DrillActionContainer> actions = null;
                if (!RotateAxes)
                {
                    actions = args.AxisIndex == 0 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                else
                {
                    actions = args.AxisIndex == 1 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                DrillActionContainer previous = null;
                DrillActionContainer container = null;

                // Родители
                if (args.Ascendants != null)
                {
                    for (int i = args.Ascendants.Count - 1; i >= 0; i--)
                    {
                        ShortMemberInfo mi = args.Ascendants[i];

                        container = History.CurrentHistoryItem.FindDrillActionContainer(actions, mi.UniqueName);
                        if (container == null)
                        {
                            container = new DrillActionContainer(mi.UniqueName, mi.HierarchyUniqueName);
                            if (previous == null)
                                actions.Add(container);
                            else
                                previous.Children.Add(container);
                        }
                        previous = container;
                    }
                }

                MdxDrillDownAction skip_container = null;
                // Сам элемент
                container = History.CurrentHistoryItem.FindDrillActionContainer(actions, args.Member.UniqueName);
                if (container == null)
                {
                    container = new DrillActionContainer(args.Member.UniqueName, args.Member.HierarchyUniqueName);
                    container.Action = new MdxExpandAction(args.Member.UniqueName);
                    if (previous == null)
                        actions.Add(container);
                    else
                        previous.Children.Add(container);
                }
                else
                {
                    // Если по данному элементу уже дедался дриллдаун - то дриллдаун остается в силе. А раскрытие - прокидываем 
                    skip_container = container.Action as MdxDrillDownAction;
                    if (skip_container == null)
                        container.Action = new MdxExpandAction(args.Member.UniqueName);
                }

                // Вложенные действия над элементами из этой же иерархии
                IList<DrillActionContainer> actionsToHierarchy = History.CurrentHistoryItem.FindDrillActionContainersByHierarchy(actions, args.Member.HierarchyUniqueName);
                if (actionsToHierarchy != null)
                {
                    // Все DrillUp и DrillDown операции зануляем если уровень у них глубже
                    foreach (DrillActionContainer action in actionsToHierarchy)
                    {
                        MdxDrillDownAction drillDownAction = action.Action as MdxDrillDownAction;
                        if (drillDownAction != null && drillDownAction.LevelDepth >= args.Member.LevelDepth)
                        {
                            if (skip_container != null && skip_container == drillDownAction)
                                continue;

                            action.Action = null;
                        }
                        MdxDrillUpAction drillUpAction = action.Action as MdxDrillUpAction;
                        if (drillUpAction != null && drillUpAction.LevelDepth >= args.Member.LevelDepth)
                        {
                            action.Action = null;
                        }
                    }
                }
            }
        }
        void CollapseMember(PerformMemberActionArgs args)
        {
            //using (WaitCursor wc = new WaitCursor())
            {
                IList<DrillActionContainer> actions = null;
                if (!RotateAxes)
                {
                    actions = args.AxisIndex == 0 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                else
                {
                    actions = args.AxisIndex == 1 ? History.CurrentHistoryItem.ColumnsActionChain : History.CurrentHistoryItem.RowsActionChain;
                }
                DrillActionContainer previous = null;
                DrillActionContainer container = null;

                // Родители
                if (args.Ascendants != null)
                {
                    for (int i = args.Ascendants.Count - 1; i >= 0; i--)
                    {
                        ShortMemberInfo mi = args.Ascendants[i];

                        container = History.CurrentHistoryItem.FindDrillActionContainer(actions, mi.UniqueName);
                        if (container == null)
                        {
                            container = new DrillActionContainer(mi.UniqueName, mi.HierarchyUniqueName);
                            if (previous == null)
                                actions.Add(container);
                            else
                                previous.Children.Add(container);
                        }
                        previous = container;
                    }
                }

                // Сам элемент
                container = History.CurrentHistoryItem.FindDrillActionContainer(actions, args.Member.UniqueName);
                if (container == null)
                {
                    container = new DrillActionContainer(args.Member.UniqueName, args.Member.HierarchyUniqueName);
                    container.Action = new MdxCollapseAction(args.Member.UniqueName);
                    if (previous == null)
                        actions.Add(container);
                    else
                        previous.Children.Add(container);
                }
                else
                {
                    // Удалем все дочерние - тем самым как бы схлопываем элемент
                    // Удаляем все вложенные экшены для данной иерархии
                    IList<DrillActionContainer> actionsToHierarchy = History.CurrentHistoryItem.FindDrillActionContainersByHierarchy(container.Children, args.Member.HierarchyUniqueName);
                    if (actionsToHierarchy != null)
                    {
                        // Все действия зануляем
                        foreach (DrillActionContainer action in actionsToHierarchy)
                        {
                            action.Action = null;
                        }
                    }
                    container.Action = new MdxCollapseAction(args.Member.UniqueName);
                }
            }
        }
        public CellSetData PerformMemberAction(PerformMemberActionArgs args)
        {
            if (args != null)
            {
                switch (args.Action)
                {
                    case MemberActionType.Expand:
                    case MemberActionType.Collapse:
                    case MemberActionType.DrillDown:
                    case MemberActionType.DrillUp:
                        // Удаляем все элементы истории, стоящие за текущим
                        History.CutRight();
                        HistoryItem clone = null;
                        if (History.CurrentHistoryItem != null)
                        {
                            // Клонируем текущий элемент истории чтобы действие добавлялось уже в клон
                            clone = (HistoryItem)(History.CurrentHistoryItem.Clone());
                        }
                        else
                        {
                            // Добавляем пустой элемент истории
                            HistoryItem first = new HistoryItem();
                            History.AddHistoryItem(first);

                            clone = new HistoryItem();
                        }

                        History.AddHistoryItem(clone);
                        break;
                }

                switch (args.Action)
                {
                    case MemberActionType.Expand:
                        ExpandMember(args);
                        break;
                    case MemberActionType.Collapse:
                        CollapseMember(args);
                        break;
                    case MemberActionType.DrillDown:
                        DrillDownMember(args);
                        break;
                    case MemberActionType.DrillUp:
                        DrillUpMember(args);
                        break;
                }
            }
            return RefreshQuery();
        }