Tabpages are jumping when moving them from bottom to top in multiline tabcontrol

We he a draggable tabpages, the implementation is similar to the approaches suggested in the topic How to make TabPages draggable?. I think that this is not a matter of our changes, since I tried the proposed approaches on pure tab control in a separate project and noticed exactly the same behavior. Has anyone faced a similar problem? Is there any reasonable solution? It seems to me, is not a good idea to disallowing drawing, because then it will not be visible where the tab is moving.

A video recording of the problem enter image description here

Link to minimal reproducable example https://drive.google.com/file/d/122u3jcTmqEOl4LcmLI4n3cEvIlds328B/view?usp=sharing

Upvotes: 1

Views: 216

Answers (1)

Loathing
Loathing

Reputation: 5266

The bottom-most row of tabs is the active row. Clicking/swapping a tab on an upper row moves that entire row to the bottom-most row. This is what is causing the jitter.

If you are dragging a TabPage along the active row then it is fine to swap the index locations in the TabPageCollection. However, as soon as an upper row tab is involved, the TabControl re-orders the rows.

One possible idea is to only change the TabPage.Text property. However, then each tab rectangle width needs to be locked, otherwise it will probably cause a jitter problem. I was playing around with the text renaming idea, the code is below. If just the text is changed, the tab highlighting also needs to be made smarter so that the destination tab appears highlighted, and the source tab no longer appears highlighted. Finally, when the drag operation is over is when the actual swap would happen, which would make the source tab's row the active row (not done in the code).

private static void swapTabPages2(TabControl tc, TabPage src, TabPage dst, DragTabData data) {
    TabPageCollection tabs = tc.TabPages;
    int n = tabs.Count;
    int index_src = tabs.IndexOf(src);
    int index_dst = tabs.IndexOf(dst);

    if (index_dst >= index_src) {
        for (int i = 0; i < index_src; i++)
            tabs[i].Text = data.OrigText[i]; // OrigText stores each tab's original Text just before this.DoDragDrop(...) is called
        for (int i = index_dst + 1; i < n; i++)
            tabs[i].Text = data.OrigText[i];

        for (int i = index_src; i < index_dst; i++)
            tabs[i].Text = data.OrigText[i+1];

        tabs[index_dst].Text = data.OrigTabText;
    }
    else {
        for (int i = 0; i < index_dst; i++)
            tabs[i].Text = data.OrigText[i];
        for (int i = index_src + 1; i < n; i++)
            tabs[i].Text = data.OrigText[i];

        for (int i = index_src; i > index_dst; i--)
            tabs[i].Text = data.OrigText[i-1];

        tabs[index_dst].Text = data.OrigTabText;
    }
}

Upvotes: 1

Related Questions