Код рефакторинга для использования пользовательского класса вместо того, который предоставляет система

Ну, это, наверное, самый глупый вопрос, но у меня есть огромная проблема, которая беспокоит меня. Во-первых, я использовал пример кода из советов по управлению вкладками Mick Doherty в позиции TabItems во время выполнения, чтобы разрешить перетаскивание моих вкладок в свой элемент управления. Проблема в том, что я использую пользовательский класс TabPage по имени ExtendedTabPage и это доставляет мне неприятности. Я пробовал кастинг или использование as Ключевое слово, но мне не повезло, поэтому я хотел бы, чтобы кто-нибудь помог мне разобраться, как изменить код, чтобы можно было перетаскивать пользовательские вкладки.

РЕДАКТИРОВАТЬ: я забыл упомянуть, что ExtendedTabPage является абстрактный класс, который наследуется моими объектами (например, одна из моих Windows принадлежит классу ConsoleTab, который наследует ExtendedTabPage). Это имеет отношение к самой проблеме?

РЕДАКТИРОВАТЬ 2: Основные открытия - В методе DragOver, если я пытаюсь использовать ConsoleTab в операторах typeof, он, кажется, работает отлично. Проблема в том, что я не хочу делать это специально для этого класса, но для всех классов, наследуемых от его родительского класса, который является абстрактным (и я могу фактически преобразовать его в неабстрактный, если это будет необходимо, но я не буду активно его использовать...).

РЕДАКТИРОВАТЬ 3: Может быть, хорошим способом было бы напрямую поменять местами с помощью индексов и избежать использования данных TabPage, однако я немного запутался, как это сделать...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using ReCodeConsole.Properties;

namespace ReCodeConsole.Core
{
    /// <summary>
    /// Implements all the extra functionality needed for tab pages on top of the existing TabControl.
    /// Includes events for DrawItem, MouseMove and MouseDown.
    /// </summary>
    public partial class ExtendedTabControl : TabControl
    {
        /// <summary>
        /// Initializes a new instance of the ExtendedTabControl class. All events are added.
        /// </summary>
        public ExtendedTabControl() :base()
        {
            this.DrawItem+=new DrawItemEventHandler(DrawTab);
            this.MouseClick+=new MouseEventHandler(Tab_OnMouseDown);
            this.MouseMove+=new MouseEventHandler(Tab_OnMouseMove);
            this.DragOver+=new DragEventHandler(Tab_OnDragOver);
        }
        /// <summary>
        /// Used to store the starting position of a tab drag event.
        /// </summary>
        private Point DragStartPosition = Point.Empty;

        private void DrawTab(object sender, DrawItemEventArgs e)
        {
            //
            //This code will render the close button at the end of the Tab caption.
            //
            e.Graphics.DrawImage(Resources.TabCloseButton, e.Bounds.Right - 22, e.Bounds.Top + 5, 14, 14);
            e.Graphics.DrawString(this.TabPages[e.Index].Text, e.Font, Brushes.Black, e.Bounds.Left + 12, e.Bounds.Top + 3);
            e.DrawFocusRectangle();
        }

        private void Tab_OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //
            // Regardless of where the MouseDown event originated, save the coordinates for dragging.
            //
            DragStartPosition = new Point(e.X, e.Y);

            #region Close Button Handling
            //
            // Close button code - looping through the controls.
            //
            for (int i = 0; i < this.TabPages.Count; i++)
            {
                Rectangle r = GetTabRect(i);
                //
                //Getting the position of the close button.
                //
                Rectangle closeButton = new Rectangle(r.Right - 22, r.Top + 5, 14, 14);
                if (closeButton.Contains(e.Location))
                {
                    if (this.TabPages[i] is ExtendedTabPage)
                    {
                        if ((this.TabPages[i] as ExtendedTabPage).IsCloseable)
                        {
                            if (MessageBox.Show("Are you sure you want to close this tab?", "Close", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                            {
                                this.TabPages.RemoveAt(i);
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (MessageBox.Show("Are you sure you want to close this tab?", "Close", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                            {
                                this.TabPages.RemoveAt(i);
                                break;
                            }
                     }
                }
            }
            #endregion

        }

        private TabPage HoverTab()
        {
            for (int index = 0; index <= TabCount - 1; index++)
            {
                if (GetTabRect(index).Contains(PointToClient(Cursor.Position)))
                    return (TabPage)TabPages[index];
            }
            return null;
        }

        private void Tab_OnDragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            TabPage hover_Tab = HoverTab();
            if (hover_Tab == null)
                e.Effect = DragDropEffects.None;
            else
            {
                if (e.Data.GetDataPresent(typeof(TabPage)))
                {
                    e.Effect = DragDropEffects.Move;
                    TabPage drag_tab = (TabPage)e.Data.GetData(typeof(TabPage));

                    if (hover_Tab == drag_tab) return;

                    Rectangle TabRect = GetTabRect(TabPages.IndexOf(hover_Tab));
                    TabRect.Inflate(-3, -3);
                    if (TabRect.Contains(PointToClient(new Point(e.X, e.Y))))
                    {
                        SwapTabPages(drag_tab, hover_Tab);
                        SelectedTab = drag_tab;
                    }
                }
            }
        }
        private void Tab_OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;

            Rectangle r = new Rectangle(DragStartPosition, Size.Empty);
            r.Inflate(SystemInformation.DragSize);

            TabPage tp = HoverTab();

            if (tp != null)
            {
                if (!r.Contains(e.X, e.Y))
                    DoDragDrop(tp, DragDropEffects.All);
            }
            DragStartPosition = Point.Empty;
        }

        private void SwapTabPages(TabPage tp1, TabPage tp2)
        {
            int Index1 = this.TabPages.IndexOf(tp1);
            int Index2 = this.TabPages.IndexOf(tp2);
            this.TabPages[Index1] = tp2;
            this.TabPages[Index2] = tp1;
        }
    }
}

Теперь игнорируйте все, что является лишним, я дам вам весь код на случай, если что-то еще испортит все это. Напомним, что я хочу, чтобы кто-то исправил код или хотя бы объяснил, как это сделать (или, если это невозможно, что сделать), чтобы я мог переключаться между элементами ExtendedTabPage вместо обычной TabPage. Я пробовал, и обычные объекты TabPage работают, в то время как мои пользовательские не работают. Если решение должно включать только один из них (поэтому обычные TabPages не могут работать), выберите только ExtendedTabPage, поскольку я могу преобразовать в него все остальное. Надеюсь, это не совсем глупая ситуация, когда я что-то упускаю.

PS: Я также проверил страницу, на которую я ссылался, для решения, которое работало для пользовательских классов, но безуспешно, так как это вызвало у меня вдвое больше проблем, и половина моего кода сломалась даже с правильными ссылками на сборки, так что это нереальный вариант.:/

1 ответ

Решение

Ну, так как никто, кажется, не знает решения и после чрезмерного тестирования и настройки, а также некоторых очень удачных находок на сайте, а именно, Как работать с GetDataPresent, чтобы позволить ему принимать все производные типы и C# Drag and Drop - e.Data.GetData, используя Базовый класс, я рад сообщить, что проблема может быть достаточно легко решена путем замены GetPresentData а также GetData звонки. Я предоставляю измененный код для Tab_OnDragOver именно там возникла проблема, и я надеюсь, что все это прекрасно работает для тех, кто заходит на эту страницу и ищет решение!

private void Tab_OnDragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            TabPage hover_Tab = HoverTab();
            if (hover_Tab == null)
                e.Effect = DragDropEffects.None;
            else
            {
                var drag_tab = e.Data.GetData(e.Data.GetFormats()[0]);
                if (typeof(TabPage).IsAssignableFrom(drag_tab.GetType()))
                {
                    e.Effect = DragDropEffects.Move;

                    if (hover_Tab == drag_tab) return;

                    Rectangle TabRect = GetTabRect(TabPages.IndexOf(hover_Tab));
                    TabRect.Inflate(-3, -3);
                    if (TabRect.Contains(PointToClient(new Point(e.X, e.Y))))
                    {
                        SwapTabPages(drag_tab as TabPage, hover_Tab);
                        SelectedTab = drag_tab as TabPage;
                    }
                }
            }
        }
Другие вопросы по тегам